mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-18 00:00:00 +00:00
add dtables
This commit is contained in:
@@ -110,7 +110,7 @@ class Table extends Component {
|
|||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>{table.modifier}</td>
|
<td>{table.modifier}</td>
|
||||||
<td>{moment(table.mtime).fromNow()}</td>
|
<td>{moment(table.updated_at).fromNow()}</td>
|
||||||
<td>
|
<td>
|
||||||
{this.state.active &&
|
{this.state.active &&
|
||||||
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down" className="mx-1 old-history-more-operation">
|
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down" className="mx-1 old-history-more-operation">
|
||||||
|
@@ -19,7 +19,7 @@ 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.api2.views import get_repo_file
|
from seahub.api2.views import get_repo_file
|
||||||
from seahub.dtable.models import Workspaces
|
from seahub.dtable.models import Workspaces, DTables
|
||||||
from seahub.tags.models import FileUUIDMap
|
from seahub.tags.models import FileUUIDMap
|
||||||
from seahub.base.templatetags.seahub_tags import email2nickname
|
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||||
@@ -117,22 +117,11 @@ class WorkspacesView(APIView):
|
|||||||
else:
|
else:
|
||||||
owner_name = email2nickname(owner)
|
owner_name = email2nickname(owner)
|
||||||
|
|
||||||
table_objs = seafile_api.list_dir_by_path(repo_id, '/')
|
table_list = DTables.objects.get_dtable_by_workspace(workspace)
|
||||||
table_list = list()
|
|
||||||
for table_obj in table_objs:
|
|
||||||
if table_obj.obj_name[-7:] != FILE_TYPE:
|
|
||||||
continue
|
|
||||||
table = dict()
|
|
||||||
table_file = seafile_api.get_dirent_by_path(repo_id, '/'+table_obj.obj_name)
|
|
||||||
table["name"] = table_file.obj_name[:-7]
|
|
||||||
table["mtime"] = timestamp_to_isoformat_timestr(table_file.mtime)
|
|
||||||
table["modifier"] = email2nickname(table_file.modifier)
|
|
||||||
table_list.append(table)
|
|
||||||
|
|
||||||
res = workspace.to_dict()
|
res = workspace.to_dict()
|
||||||
res["owner_name"] = owner_name
|
res["owner_name"] = owner_name
|
||||||
res["table_list"] = table_list
|
res["table_list"] = table_list
|
||||||
res["updated_at"] = workspace.updated_at
|
|
||||||
workspace_list.append(res)
|
workspace_list.append(res)
|
||||||
|
|
||||||
return Response({"workspace_list": workspace_list}, status=status.HTTP_200_OK)
|
return Response({"workspace_list": workspace_list}, status=status.HTTP_200_OK)
|
||||||
@@ -225,19 +214,19 @@ class DTablesView(APIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
seafile_api.post_empty_file(repo_id, '/', table_file_name, username)
|
seafile_api.post_empty_file(repo_id, '/', table_file_name, username)
|
||||||
except SearpcError, e:
|
except SearpcError 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)
|
||||||
|
|
||||||
table_path = normalize_file_path(table_file_name)
|
try:
|
||||||
table_obj = seafile_api.get_dirent_by_path(repo_id, table_path)
|
dtable = DTables.objects.create_dtable(table_owner, workspace, table_name)
|
||||||
table = dict()
|
except Exception as e:
|
||||||
table["name"] = table_obj.obj_name[:-7]
|
logger.error(e)
|
||||||
table["mtime"] = timestamp_to_isoformat_timestr(table_obj.mtime)
|
error_msg = 'Internal Server Error'
|
||||||
table["modifier"] = email2nickname(table_obj.modifier)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
return Response({"table": table}, status=status.HTTP_201_CREATED)
|
return Response({"table": dtable.to_dict()}, status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
class DTableView(APIView):
|
class DTableView(APIView):
|
||||||
@@ -272,11 +261,16 @@ class DTableView(APIView):
|
|||||||
error_msg = 'Library %s not found.' % repo_id
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
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)
|
||||||
|
|
||||||
table_file_name = table_name + FILE_TYPE
|
table_file_name = table_name + FILE_TYPE
|
||||||
table_path = normalize_file_path(table_file_name)
|
table_path = normalize_file_path(table_file_name)
|
||||||
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
||||||
if not table_file_id:
|
if not table_file_id:
|
||||||
error_msg = 'table %s not found.' % table_name
|
error_msg = 'file %s not found.' % table_file_name
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
# permission check
|
# permission check
|
||||||
@@ -334,11 +328,16 @@ class DTableView(APIView):
|
|||||||
error_msg = 'Library %s not found.' % repo_id
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
dtable = DTables.objects.get_dtable(workspace, old_table_name)
|
||||||
|
if not dtable:
|
||||||
|
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
|
old_table_file_name = old_table_name + FILE_TYPE
|
||||||
old_table_path = normalize_file_path(old_table_file_name)
|
old_table_path = normalize_file_path(old_table_file_name)
|
||||||
table_file_id = seafile_api.get_file_id_by_path(repo_id, old_table_path)
|
table_file_id = seafile_api.get_file_id_by_path(repo_id, old_table_path)
|
||||||
if not table_file_id:
|
if not table_file_id:
|
||||||
error_msg = 'table %s not found.' % old_table_name
|
error_msg = 'file %s not found.' % old_table_file_name
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
# permission check
|
# permission check
|
||||||
@@ -369,14 +368,16 @@ class DTableView(APIView):
|
|||||||
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_table_path = normalize_file_path(new_table_file_name)
|
try:
|
||||||
table_obj = seafile_api.get_dirent_by_path(repo_id, new_table_path)
|
dtable.name = new_table_name
|
||||||
table = dict()
|
dtable.modifier = username
|
||||||
table["name"] = table_obj.obj_name[:-7]
|
dtable.save()
|
||||||
table["mtime"] = timestamp_to_isoformat_timestr(table_obj.mtime)
|
except Exception as e:
|
||||||
table["modifier"] = email2nickname(table_obj.modifier)
|
logger.error(e)
|
||||||
|
error_msg = 'Internal Server Error.'
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
return Response({"table": table}, status=status.HTTP_200_OK)
|
return Response({"table": dtable.to_dict()}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def delete(self, request, workspace_id):
|
def delete(self, request, workspace_id):
|
||||||
"""delete a table
|
"""delete a table
|
||||||
@@ -400,10 +401,16 @@ class DTableView(APIView):
|
|||||||
error_msg = 'Library %s not found.' % repo_id
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
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)
|
||||||
|
|
||||||
table_path = normalize_file_path(table_file_name)
|
table_path = normalize_file_path(table_file_name)
|
||||||
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
||||||
if not table_file_id:
|
if not table_file_id:
|
||||||
return Response({'success': True}, status=status.HTTP_200_OK)
|
error_msg = 'file %s not found.' % table_file_name
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
# permission check
|
# permission check
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
@@ -425,8 +432,7 @@ class DTableView(APIView):
|
|||||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
# delete asset
|
# delete asset
|
||||||
uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, '/', table_file_name, is_dir=False)
|
asset_dir_path = '/asset/' + str(dtable.uuid)
|
||||||
asset_dir_path = '/asset/' + str(uuid.uuid)
|
|
||||||
asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path)
|
asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path)
|
||||||
if asset_dir_id:
|
if asset_dir_id:
|
||||||
parent_dir = os.path.dirname(asset_dir_path)
|
parent_dir = os.path.dirname(asset_dir_path)
|
||||||
@@ -438,9 +444,6 @@ class DTableView(APIView):
|
|||||||
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)
|
||||||
|
|
||||||
# delete uuid
|
|
||||||
uuid.delete()
|
|
||||||
|
|
||||||
# delete table
|
# delete table
|
||||||
try:
|
try:
|
||||||
seafile_api.del_file(repo_id, '/', table_file_name, owner)
|
seafile_api.del_file(repo_id, '/', table_file_name, owner)
|
||||||
@@ -449,6 +452,13 @@ class DTableView(APIView):
|
|||||||
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)
|
||||||
|
|
||||||
|
try:
|
||||||
|
DTables.objects.delete_dtable(workspace, table_name)
|
||||||
|
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)
|
return Response({'success': True}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
@@ -461,6 +471,12 @@ class DTableUpdateLinkView(APIView):
|
|||||||
def get(self, request, workspace_id):
|
def get(self, request, workspace_id):
|
||||||
"""get table file update link
|
"""get table file update link
|
||||||
"""
|
"""
|
||||||
|
# argument check
|
||||||
|
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)
|
||||||
|
|
||||||
# resource check
|
# resource check
|
||||||
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
|
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
|
||||||
if not workspace:
|
if not workspace:
|
||||||
@@ -473,6 +489,11 @@ class DTableUpdateLinkView(APIView):
|
|||||||
error_msg = 'Library %s not found.' % repo_id
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
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
|
# permission check
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
owner = workspace.owner
|
owner = workspace.owner
|
||||||
@@ -494,6 +515,9 @@ class DTableUpdateLinkView(APIView):
|
|||||||
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)
|
||||||
|
|
||||||
|
dtable.modifier = username
|
||||||
|
dtable.save()
|
||||||
|
|
||||||
url = gen_file_upload_url(token, 'update-api')
|
url = gen_file_upload_url(token, 'update-api')
|
||||||
return Response(url)
|
return Response(url)
|
||||||
|
|
||||||
@@ -512,7 +536,6 @@ class DTableAssetUploadLinkView(APIView):
|
|||||||
if not table_name:
|
if not table_name:
|
||||||
error_msg = 'name invalid.'
|
error_msg = 'name invalid.'
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
table_file_name = table_name + FILE_TYPE
|
|
||||||
|
|
||||||
# resource check
|
# resource check
|
||||||
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
|
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
|
||||||
@@ -526,6 +549,11 @@ class DTableAssetUploadLinkView(APIView):
|
|||||||
error_msg = 'Library %s not found.' % repo_id
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
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
|
# permission check
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
owner = workspace.owner
|
owner = workspace.owner
|
||||||
@@ -542,16 +570,16 @@ class DTableAssetUploadLinkView(APIView):
|
|||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
upload_link = gen_file_upload_url(token, 'upload-api')
|
upload_link = gen_file_upload_url(token, 'upload-api')
|
||||||
uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, '/',
|
|
||||||
table_file_name,
|
|
||||||
is_dir=False)
|
|
||||||
|
|
||||||
# create asset dir
|
# create asset dir
|
||||||
asset_dir_path = '/asset/' + str(uuid.uuid)
|
asset_dir_path = '/asset/' + str(dtable.uuid)
|
||||||
asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path)
|
asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path)
|
||||||
if not asset_dir_id:
|
if not asset_dir_id:
|
||||||
seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], owner)
|
seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], owner)
|
||||||
|
|
||||||
|
dtable.modifier = username
|
||||||
|
dtable.save()
|
||||||
|
|
||||||
res = dict()
|
res = dict()
|
||||||
res['upload_link'] = upload_link
|
res['upload_link'] = upload_link
|
||||||
res['parent_path'] = asset_dir_path
|
res['parent_path'] = asset_dir_path
|
||||||
@@ -571,6 +599,10 @@ def dtable_file_view(request, workspace_id, name):
|
|||||||
if not repo:
|
if not repo:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
dtable = DTables.objects.get_dtable(workspace, name)
|
||||||
|
if not dtable:
|
||||||
|
return render_error(request, _(u'Table does not exist'))
|
||||||
|
|
||||||
table_file_name = name + FILE_TYPE
|
table_file_name = name + FILE_TYPE
|
||||||
table_path = normalize_file_path(table_file_name)
|
table_path = normalize_file_path(table_file_name)
|
||||||
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
|
||||||
@@ -623,6 +655,10 @@ def dtable_asset_access(request, workspace_id, dtable_id, path):
|
|||||||
if not repo:
|
if not repo:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
dtable = DTables.objects.get_dtable_by_uuid(dtable_id)
|
||||||
|
if not dtable:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
asset_path = normalize_file_path(os.path.join('/asset', dtable_id, path))
|
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)
|
asset_id = seafile_api.get_file_id_by_path(repo_id, asset_path)
|
||||||
if not asset_id:
|
if not asset_id:
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.15 on 2019-06-05 05:21
|
# Generated by Django 1.11.15 on 2019-06-25 05:37
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
@@ -13,21 +15,41 @@ class Migration(migrations.Migration):
|
|||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DTables',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True)),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
('creator', models.CharField(max_length=255)),
|
||||||
|
('modifier', models.CharField(max_length=255)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'dtables',
|
||||||
|
},
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Workspaces',
|
name='Workspaces',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=255)),
|
('name', models.CharField(max_length=255, null=True)),
|
||||||
('owner', models.CharField(max_length=255)),
|
('owner', models.CharField(max_length=255, unique=True)),
|
||||||
('repo_id', models.CharField(db_index=True, max_length=36)),
|
('repo_id', models.CharField(max_length=36, unique=True)),
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'workspaces',
|
'db_table': 'workspaces',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='dtables',
|
||||||
|
name='workspace',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dtable.Workspaces'),
|
||||||
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name='workspaces',
|
name='dtables',
|
||||||
unique_together=set([('owner', 'repo_id')]),
|
unique_together=set([('workspace', 'name')]),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.15 on 2019-06-21 09:37
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('dtable', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='workspaces',
|
|
||||||
name='created_at',
|
|
||||||
field=models.DateTimeField(auto_now_add=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='workspaces',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=255, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='workspaces',
|
|
||||||
name='owner',
|
|
||||||
field=models.CharField(max_length=255, unique=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='workspaces',
|
|
||||||
name='repo_id',
|
|
||||||
field=models.CharField(max_length=36, unique=True),
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='workspaces',
|
|
||||||
unique_together=set([]),
|
|
||||||
),
|
|
||||||
]
|
|
@@ -1,10 +1,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
import uuid
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from seaserv import seafile_api
|
from seaserv import seafile_api
|
||||||
|
|
||||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
||||||
|
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||||
|
|
||||||
|
|
||||||
class WorkspacesManager(models.Manager):
|
class WorkspacesManager(models.Manager):
|
||||||
@@ -65,5 +68,85 @@ class Workspaces(models.Model):
|
|||||||
return {
|
return {
|
||||||
'id': self.pk,
|
'id': self.pk,
|
||||||
'repo_id': self.repo_id,
|
'repo_id': self.repo_id,
|
||||||
'created_at': datetime_to_isoformat_timestr(self.created_at),
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DTablesManager(models.Manager):
|
||||||
|
|
||||||
|
def get_dtable_by_workspace(self, workspace):
|
||||||
|
try:
|
||||||
|
dtables = super(DTablesManager, self).filter(workspace=workspace)
|
||||||
|
dtable_list = list()
|
||||||
|
for dtable in dtables:
|
||||||
|
dtable_dict = dict()
|
||||||
|
dtable_dict['id'] = dtable.pk
|
||||||
|
dtable_dict['workspace_id'] = dtable.workspace_id
|
||||||
|
dtable_dict['uuid'] = dtable.uuid
|
||||||
|
dtable_dict['name'] = dtable.name
|
||||||
|
dtable_dict['creator'] = email2nickname(dtable.creator)
|
||||||
|
dtable_dict['modifier'] = email2nickname(dtable.modifier)
|
||||||
|
dtable_dict['created_at'] = datetime_to_isoformat_timestr(dtable.created_at)
|
||||||
|
dtable_dict['updated_at'] = datetime_to_isoformat_timestr(dtable.updated_at)
|
||||||
|
dtable_list.append(dtable_dict)
|
||||||
|
return dtable_list
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def create_dtable(self, owner, workspace, name):
|
||||||
|
try:
|
||||||
|
return super(DTablesManager, self).get(workspace=workspace, name=name)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
dtable = self.model(workspace=workspace, name=name,
|
||||||
|
creator=owner, modifier=owner)
|
||||||
|
dtable.save()
|
||||||
|
return dtable
|
||||||
|
|
||||||
|
def get_dtable(self, workspace, name):
|
||||||
|
try:
|
||||||
|
return super(DTablesManager, self).get(workspace=workspace, name=name)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_dtable_by_uuid(self, uuid):
|
||||||
|
try:
|
||||||
|
return super(DTablesManager, self).get(uuid=uuid)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def delete_dtable(self, workspace, name):
|
||||||
|
try:
|
||||||
|
dtable = super(DTablesManager, self).get(workspace=workspace, name=name)
|
||||||
|
dtable.delete()
|
||||||
|
return True
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class DTables(models.Model):
|
||||||
|
|
||||||
|
workspace = models.ForeignKey(Workspaces, on_delete=models.CASCADE, db_index=True)
|
||||||
|
uuid = models.UUIDField(unique=True, default=uuid.uuid4)
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
creator = models.CharField(max_length=255)
|
||||||
|
modifier = models.CharField(max_length=255)
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
objects = DTablesManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = (('workspace', 'name'),)
|
||||||
|
db_table = 'dtables'
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': self.pk,
|
||||||
|
'workspace_id': self.workspace_id,
|
||||||
|
'uuid': self.uuid,
|
||||||
|
'name': self.name,
|
||||||
|
'creator': email2nickname(self.creator),
|
||||||
|
'modifier': email2nickname(self.modifier),
|
||||||
|
'created_at': datetime_to_isoformat_timestr(self.created_at),
|
||||||
|
'updated_at': datetime_to_isoformat_timestr(self.updated_at),
|
||||||
}
|
}
|
||||||
|
@@ -13,13 +13,20 @@ class WorkspacesViewTest(BaseTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.workspace = Workspaces.objects.create_workspace(
|
self.workspace = Workspaces.objects.create_workspace(
|
||||||
"workspace1",
|
|
||||||
self.user.username,
|
self.user.username,
|
||||||
self.repo.id
|
self.repo.id
|
||||||
)
|
)
|
||||||
self.url = reverse('api-v2.1-workspaces')
|
self.url = reverse('api-v2.1-workspaces')
|
||||||
self.login_as(self.user)
|
self.login_as(self.user)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
assert len(Workspaces.objects.all()) == 1
|
||||||
|
|
||||||
|
workspace = Workspaces.objects.get_workspace_by_owner(self.user.username)
|
||||||
|
workspace_id = workspace.id
|
||||||
|
|
||||||
|
Workspaces.objects.delete_workspace(workspace_id)
|
||||||
|
|
||||||
def test_can_list(self):
|
def test_can_list(self):
|
||||||
assert len(Workspaces.objects.all()) == 1
|
assert len(Workspaces.objects.all()) == 1
|
||||||
|
|
||||||
@@ -43,83 +50,28 @@ class WorkspacesViewTest(BaseTestCase):
|
|||||||
assert json_resp["workspace_list"] == []
|
assert json_resp["workspace_list"] == []
|
||||||
assert len(Workspaces.objects.all()) == 1
|
assert len(Workspaces.objects.all()) == 1
|
||||||
|
|
||||||
def test_can_create(self):
|
|
||||||
assert len(Workspaces.objects.all()) == 1
|
|
||||||
|
|
||||||
resp = self.client.post(self.url, {'name': 'workspace2'})
|
|
||||||
self.assertEqual(201, resp.status_code)
|
|
||||||
|
|
||||||
assert len(Workspaces.objects.all()) == 2
|
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
|
||||||
assert json_resp["workspace"]["name"] == 'workspace2'
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceViewTest(BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.workspace = Workspaces.objects.create_workspace(
|
|
||||||
"workspace3",
|
|
||||||
self.user.username,
|
|
||||||
self.repo.id
|
|
||||||
)
|
|
||||||
self.url = reverse('api-v2.1-workspace', args=[self.workspace.id])
|
|
||||||
self.login_as(self.user)
|
|
||||||
|
|
||||||
def test_can_rename(self):
|
|
||||||
data = 'name=%s' % 'workspace4'
|
|
||||||
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["workspace"]["name"] == 'workspace4'
|
|
||||||
|
|
||||||
def test_rename_with_invalid_permission(self):
|
|
||||||
self.logout()
|
|
||||||
self.login_as(self.admin)
|
|
||||||
|
|
||||||
data = 'name=%s' % 'workspace5'
|
|
||||||
resp = self.client.put(self.url, data, 'application/x-www-form-urlencoded')
|
|
||||||
self.assertEqual(403, resp.status_code)
|
|
||||||
|
|
||||||
def test_rename_with_invalid_repo(self):
|
|
||||||
url = reverse('api2-repo', args=[self.workspace.repo_id])
|
|
||||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
|
||||||
self.assertEqual(200, resp.status_code)
|
|
||||||
|
|
||||||
data = 'name=%s' % 'workspace6'
|
|
||||||
resp = self.client.put(self.url, data, 'application/x-www-form-urlencoded')
|
|
||||||
self.assertEqual(404, resp.status_code)
|
|
||||||
|
|
||||||
def test_can_delete(self):
|
|
||||||
assert len(Workspaces.objects.all()) == 1
|
|
||||||
|
|
||||||
resp = self.client.delete(self.url, {'name': 'workspace3'})
|
|
||||||
self.assertEqual(200, resp.status_code)
|
|
||||||
|
|
||||||
assert len(Workspaces.objects.all()) == 0
|
|
||||||
|
|
||||||
def test_delete_with_invalid_permission(self):
|
|
||||||
self.logout()
|
|
||||||
self.login_as(self.admin)
|
|
||||||
|
|
||||||
resp = self.client.delete(self.url, {'name': 'workspace3'})
|
|
||||||
self.assertEqual(403, resp.status_code)
|
|
||||||
|
|
||||||
|
|
||||||
class DTableTest(BaseTestCase):
|
class DTableTest(BaseTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.workspace = Workspaces.objects.create_workspace(
|
self.workspace = Workspaces.objects.create_workspace(
|
||||||
"workspace",
|
|
||||||
self.user.username,
|
self.user.username,
|
||||||
self.repo.id
|
self.repo.id
|
||||||
)
|
)
|
||||||
self.url = reverse('api-v2.1-workspace-dtable', args=[self.workspace.id])
|
self.url1 = reverse('api-v2.1-dtables')
|
||||||
|
self.url2 = reverse('api-v2.1-workspace-dtable', args=[self.workspace.id])
|
||||||
self.login_as(self.user)
|
self.login_as(self.user)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
assert len(Workspaces.objects.all()) == 1
|
||||||
|
|
||||||
|
workspace = Workspaces.objects.get_workspace_by_owner(self.user.username)
|
||||||
|
workspace_id = workspace.id
|
||||||
|
|
||||||
|
Workspaces.objects.delete_workspace(workspace_id)
|
||||||
|
|
||||||
def test_can_create(self):
|
def test_can_create(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table1'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
@@ -130,18 +82,18 @@ class DTableTest(BaseTestCase):
|
|||||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
resp = self.client.post(self.url, {'name': 'table2'})
|
resp = self.client.post(self.url1, {'name': 'table2'})
|
||||||
self.assertEqual(404, resp.status_code)
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
def test_can_rename(self):
|
def test_can_rename(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table3'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
assert json_resp["table"]["name"] == 'table3'
|
assert json_resp["table"]["name"] == 'table3'
|
||||||
|
|
||||||
resp = self.client.put(
|
resp = self.client.put(
|
||||||
self.url,
|
self.url2,
|
||||||
'old_name=table3&new_name=table4',
|
'old_name=table3&new_name=table4',
|
||||||
'application/x-www-form-urlencoded'
|
'application/x-www-form-urlencoded'
|
||||||
)
|
)
|
||||||
@@ -152,7 +104,7 @@ class DTableTest(BaseTestCase):
|
|||||||
assert json_resp["table"]["name"] == 'table4'
|
assert json_resp["table"]["name"] == 'table4'
|
||||||
|
|
||||||
def test_rename_with_invalid_workspace(self):
|
def test_rename_with_invalid_workspace(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table5'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
@@ -164,7 +116,7 @@ class DTableTest(BaseTestCase):
|
|||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
resp = self.client.put(
|
resp = self.client.put(
|
||||||
self.url,
|
self.url2,
|
||||||
'old_name=table5&new_name=table6',
|
'old_name=table5&new_name=table6',
|
||||||
'application/x-www-form-urlencoded'
|
'application/x-www-form-urlencoded'
|
||||||
)
|
)
|
||||||
@@ -172,18 +124,18 @@ class DTableTest(BaseTestCase):
|
|||||||
self.assertEqual(404, resp.status_code)
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
def test_can_delete(self):
|
def test_can_delete(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table7'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
assert json_resp["table"]["name"] == 'table7'
|
assert json_resp["table"]["name"] == 'table7'
|
||||||
|
|
||||||
data = 'name=%s' % 'table7'
|
data = 'name=%s' % 'table7'
|
||||||
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
|
resp = self.client.delete(self.url2, data, 'application/x-www-form-urlencoded')
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
def test_delete_with_invalid_permission(self):
|
def test_delete_with_invalid_permission(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table8'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
@@ -193,11 +145,11 @@ class DTableTest(BaseTestCase):
|
|||||||
self.login_as(self.admin)
|
self.login_as(self.admin)
|
||||||
|
|
||||||
data = 'name=%s' % 'table8'
|
data = 'name=%s' % 'table8'
|
||||||
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
|
resp = self.client.delete(self.url2, data, 'application/x-www-form-urlencoded')
|
||||||
self.assertEqual(403, resp.status_code)
|
self.assertEqual(403, resp.status_code)
|
||||||
|
|
||||||
def test_delete_with_repo_only_read(self):
|
def test_delete_with_repo_only_read(self):
|
||||||
resp = self.client.post(self.url, {'name': 'table9'})
|
resp = self.client.post(self.url1, {'name': 'table1', 'owner': self.user.username})
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
@@ -206,5 +158,5 @@ class DTableTest(BaseTestCase):
|
|||||||
seafile_api.set_repo_status(self.workspace.repo_id, 1)
|
seafile_api.set_repo_status(self.workspace.repo_id, 1)
|
||||||
|
|
||||||
data = 'name=%s' % 'table9'
|
data = 'name=%s' % 'table9'
|
||||||
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
|
resp = self.client.delete(self.url2, data, 'application/x-www-form-urlencoded')
|
||||||
self.assertEqual(403, resp.status_code)
|
self.assertEqual(403, resp.status_code)
|
||||||
|
@@ -6,17 +6,18 @@ from seahub.test_utils import BaseTestCase
|
|||||||
|
|
||||||
class WorkspacesManagerTest(BaseTestCase):
|
class WorkspacesManagerTest(BaseTestCase):
|
||||||
|
|
||||||
def test_get_workspaces_by_owner(self):
|
def test_get_workspace_by_owner(self):
|
||||||
assert len(Workspaces.objects.all()) == 0
|
assert len(Workspaces.objects.all()) == 0
|
||||||
Workspaces.objects.create_workspace("test_name", self.user.username, self.repo.id)
|
Workspaces.objects.create_workspace(self.user.username, self.repo.id)
|
||||||
|
|
||||||
workspace_list = Workspaces.objects.get_workspaces_by_owner(self.user.username)
|
workspace = Workspaces.objects.get_workspace_by_owner(self.user.username)
|
||||||
|
|
||||||
assert len(workspace_list) == 1
|
assert workspace is not None
|
||||||
|
assert len(Workspaces.objects.all()) == 1
|
||||||
|
|
||||||
def test_get_workspace_by_id(self):
|
def test_get_workspace_by_id(self):
|
||||||
assert len(Workspaces.objects.all()) == 0
|
assert len(Workspaces.objects.all()) == 0
|
||||||
workspace = Workspaces.objects.create_workspace("test_name", self.user.username, self.repo.id)
|
workspace = Workspaces.objects.create_workspace(self.user.username, self.repo.id)
|
||||||
|
|
||||||
assert workspace is not None
|
assert workspace is not None
|
||||||
workspace_id = workspace.id
|
workspace_id = workspace.id
|
||||||
@@ -26,7 +27,7 @@ class WorkspacesManagerTest(BaseTestCase):
|
|||||||
|
|
||||||
def test_delete_workspace(self):
|
def test_delete_workspace(self):
|
||||||
assert len(Workspaces.objects.all()) == 0
|
assert len(Workspaces.objects.all()) == 0
|
||||||
workspace = Workspaces.objects.create_workspace("test_name", self.user.username, self.repo.id)
|
workspace = Workspaces.objects.create_workspace(self.user.username, self.repo.id)
|
||||||
|
|
||||||
assert len(Workspaces.objects.all()) == 1
|
assert len(Workspaces.objects.all()) == 1
|
||||||
workspace_id = workspace.id
|
workspace_id = workspace.id
|
||||||
|
Reference in New Issue
Block a user