mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 15:38:15 +00:00
add api
1. add repo history api. 1. add repo trash api. 1. udpate search file api, add 'content_highlight' to search result
This commit is contained in:
120
seahub/api2/endpoints/repo_history.py
Normal file
120
seahub/api2/endpoints/repo_history.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||
import logging
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
from seahub.options.models import UserOptions, CryptoOptionNotSetError
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.utils import new_merge_with_no_conflict
|
||||
from seahub.views import check_folder_permission
|
||||
|
||||
from seaserv import seafile_api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class RepoHistory(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated, )
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def get_item_info(self, commit):
|
||||
|
||||
item_info = {
|
||||
'creator': commit.creator_name,
|
||||
'time': timestamp_to_isoformat_timestr(commit.ctime),
|
||||
'description': commit.desc,
|
||||
'commit_id': commit.id,
|
||||
}
|
||||
|
||||
return item_info
|
||||
|
||||
def get(self, request, repo_id, format=None):
|
||||
""" Return history of library
|
||||
|
||||
Permission checking:
|
||||
1. all authenticated user can perform this action.
|
||||
"""
|
||||
|
||||
# resource check
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if check_folder_permission(request, repo_id, '/') is None:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
try:
|
||||
server_crypto = UserOptions.objects.is_server_crypto(username)
|
||||
except CryptoOptionNotSetError:
|
||||
# Assume server_crypto is ``False`` if this option is not set.
|
||||
server_crypto = False
|
||||
|
||||
password_set = False
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)):
|
||||
try:
|
||||
ret = seafile_api.is_passwd_set(repo_id, username)
|
||||
if ret == 1:
|
||||
password_set = True
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not password_set:
|
||||
error_msg = 'Library is encrypted, but password is not set in server.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
page = int(request.GET.get('page', '1'))
|
||||
per_page = int(request.GET.get('per_page', '100'))
|
||||
except ValueError:
|
||||
page = 1
|
||||
per_page = 100
|
||||
|
||||
if page <= 0:
|
||||
error_msg = 'page invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
if per_page <= 0:
|
||||
error_msg = 'per_page invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
start = (page - 1) * per_page
|
||||
limit = per_page + 1
|
||||
|
||||
try:
|
||||
all_commits = seafile_api.get_commit_list(repo_id, start, limit)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
items = []
|
||||
commits = all_commits[:per_page]
|
||||
for commit in commits:
|
||||
if new_merge_with_no_conflict(commit):
|
||||
continue
|
||||
|
||||
item_info = self.get_item_info(commit)
|
||||
items.append(item_info)
|
||||
|
||||
result = {
|
||||
'data': items,
|
||||
'more': True if len(all_commits) == per_page + 1 else False
|
||||
}
|
||||
|
||||
return Response(result)
|
117
seahub/api2/endpoints/repo_trash.py
Normal file
117
seahub/api2/endpoints/repo_trash.py
Normal file
@@ -0,0 +1,117 @@
|
||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||
import stat
|
||||
import logging
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.views import check_folder_permission
|
||||
|
||||
from seaserv import seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class RepoTrash(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated, )
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def get_item_info(self, trash_item):
|
||||
|
||||
item_info = {
|
||||
'parent_dir': trash_item.basedir,
|
||||
'obj_name': trash_item.obj_name,
|
||||
'deleted_time': timestamp_to_isoformat_timestr(trash_item.delete_time),
|
||||
'scan_stat': trash_item.scan_stat,
|
||||
'commit_id': trash_item.commit_id,
|
||||
}
|
||||
|
||||
if stat.S_ISDIR(trash_item.mode):
|
||||
is_dir = True
|
||||
else:
|
||||
is_dir = False
|
||||
|
||||
item_info['is_dir'] = is_dir
|
||||
item_info['size'] = trash_item.file_size if not is_dir else ''
|
||||
item_info['obj_id'] = trash_item.obj_id if not is_dir else ''
|
||||
|
||||
return item_info
|
||||
|
||||
def get(self, request, repo_id, format=None):
|
||||
""" Return deleted files/dirs of a repo/folder
|
||||
|
||||
Permission checking:
|
||||
1. all authenticated user can perform this action.
|
||||
"""
|
||||
|
||||
# argument check
|
||||
path = request.GET.get('path', '/')
|
||||
|
||||
# resource check
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
try:
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not dir_id:
|
||||
error_msg = 'Folder %s not found.' % path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if check_folder_permission(request, repo_id, path) is None:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
show_days = int(request.GET.get('show_days', '0'))
|
||||
except ValueError:
|
||||
show_days = 0
|
||||
|
||||
if show_days < 0:
|
||||
error_msg = 'show_days invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
scan_stat = request.GET.get('scan_stat', None)
|
||||
try:
|
||||
# a list will be returned, with at least 1 item in it
|
||||
# the last item is not a deleted entry, and it contains an attribute named 'scan_stat'
|
||||
deleted_entries = seafile_api.get_deleted(repo_id,
|
||||
show_days, path, scan_stat)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
scan_stat = deleted_entries[-1].scan_stat
|
||||
more = True if scan_stat is not None else False
|
||||
|
||||
items = []
|
||||
if len(deleted_entries) > 1:
|
||||
for item in deleted_entries[0:-1]:
|
||||
item_info = self.get_item_info(item)
|
||||
items.append(item_info)
|
||||
|
||||
result = {
|
||||
'data': items,
|
||||
'more': more,
|
||||
'scan_stat': scan_stat,
|
||||
}
|
||||
|
||||
return Response(result)
|
@@ -323,7 +323,6 @@ class Search(APIView):
|
||||
results, total, has_more = search_keyword(request, keyword)
|
||||
for e in results:
|
||||
e.pop('repo', None)
|
||||
e.pop('content_highlight', None)
|
||||
e.pop('exists', None)
|
||||
e.pop('last_modified_by', None)
|
||||
e.pop('name_highlight', None)
|
||||
|
@@ -28,6 +28,8 @@ from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
|
||||
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink
|
||||
from seahub.api2.endpoints.file import FileView
|
||||
from seahub.api2.endpoints.dir import DirView
|
||||
from seahub.api2.endpoints.repo_trash import RepoTrash
|
||||
from seahub.api2.endpoints.repo_history import RepoHistory
|
||||
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
|
||||
from seahub.api2.endpoints.zip_task import ZipTaskView
|
||||
from seahub.api2.endpoints.share_link_zip_task import ShareLinkZipTaskView
|
||||
@@ -212,6 +214,8 @@ urlpatterns = patterns(
|
||||
## user::repos
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/trash/$', RepoTrash.as_view(), name='api-v2.1-repo-trash'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/history/$', RepoHistory.as_view(), name='api-v2.1-repo-history'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
||||
|
||||
## user::download-dir-zip-task
|
||||
|
23
tests/api/endpoints/test_repo_history.py
Normal file
23
tests/api/endpoints/test_repo_history.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seahub.test_utils import BaseTestCase
|
||||
|
||||
class RepoHistoryTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.repo_id = self.repo.id
|
||||
self.user_name = self.user.username
|
||||
self.url = reverse('api-v2.1-repo-history', args=[self.repo_id])
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
self.remove_group()
|
||||
|
||||
def test_can_get(self):
|
||||
self.login_as(self.user)
|
||||
resp = self.client.get(self.url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['data'][0]['creator'] == self.user_name
|
30
tests/api/endpoints/test_repo_trash.py
Normal file
30
tests/api/endpoints/test_repo_trash.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import os
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seaserv import seafile_api
|
||||
from seahub.test_utils import BaseTestCase
|
||||
|
||||
class RepoTrashTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.repo_id = self.repo.id
|
||||
self.user_name = self.user.username
|
||||
self.url = reverse('api-v2.1-repo-trash', args=[self.repo_id])
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
self.remove_group()
|
||||
|
||||
def test_can_get(self):
|
||||
# delete a file first
|
||||
file_name = os.path.basename(self.file)
|
||||
seafile_api.del_file(self.repo_id, '/', file_name, self.user_name)
|
||||
|
||||
self.login_as(self.user)
|
||||
resp = self.client.get(self.url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['data'][0]['obj_name'] == file_name
|
||||
assert json_resp['data'][0]['is_dir'] == False
|
Reference in New Issue
Block a user