From 734766391ae7dd38ac2c8f18137f6a1e24675c85 Mon Sep 17 00:00:00 2001 From: zming <517046497@qq.com> Date: Fri, 23 Jun 2017 10:35:41 +0800 Subject: [PATCH 1/3] [api2] get deleted-repos,and restore deleted-repos --- seahub/api2/endpoints/deleted_repos.py | 70 +++++++++++++++++++++++ seahub/urls.py | 2 + tests/api/endpoints/test_deleted_repos.py | 47 +++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 seahub/api2/endpoints/deleted_repos.py create mode 100644 tests/api/endpoints/test_deleted_repos.py diff --git a/seahub/api2/endpoints/deleted_repos.py b/seahub/api2/endpoints/deleted_repos.py new file mode 100644 index 0000000000..77826c9a7e --- /dev/null +++ b/seahub/api2/endpoints/deleted_repos.py @@ -0,0 +1,70 @@ +import logging + +from rest_framework.authentication import SessionAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework import status +from django.template.defaultfilters import filesizeformat +from seaserv import seafile_api + +from pysearpc import SearpcError + +from seahub.api2.throttling import UserRateThrottle +from seahub.api2.authentication import TokenAuthentication +from seahub.api2.base import APIView +from seahub.api2.utils import api_error +from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email +from seahub.utils.timeutils import timestamp_to_isoformat_timestr + +logger = logging.getLogger(__name__) + + +class DeletedRepos(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication) + permission_classes = (IsAuthenticated,) + throttle_classes = (UserRateThrottle,) + + def get(self, request): + """ + get the deleted-repos of owner + """ + trashs_json = [] + email = request.user.username + + trash_repos = seafile_api.get_trash_repos_by_owner(email) + for r in trash_repos: + trash = { + "repo_id": r.repo_id, + "owner_email": email, + "owner_name": email2nickname(email), + "owner_contact_email": email2contact_email(email), + "repo_name": r.repo_name, + "org_id": r.org_id, + "head_commit_id": r.head_id, + "encrypted": r.encrypted, + "del_time": timestamp_to_isoformat_timestr(r.del_time), + "size": r.size, + } + trashs_json.append(trash) + return Response(trashs_json) + + def post(self, request): + """ + restore deleted-repo + return: + return True if success, otherwise api_error + """ + post_data = request.POST + repo_id = post_data.get('repo_id', '') + if not repo_id: + error_msg = "repo_id invalid" + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + try: + seafile_api.restore_repo_from_trash(repo_id) + except SearpcError as e: + logger.error(e) + error = "Internal Server Error" + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + return Response({"success": True}) diff --git a/seahub/urls.py b/seahub/urls.py index da5ac9fa5b..c42ea799ea 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -30,6 +30,7 @@ from seahub.api2.endpoints.repos import RepoView 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.deleted_repos import DeletedRepos 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 @@ -209,6 +210,7 @@ urlpatterns = patterns( ## user::repos url(r'^api/v2.1/repos/batch/$', ReposBatchView.as_view(), name='api-v2.1-repos-batch'), url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/$', RepoView.as_view(), name='api-v2.1-repo-view'), + url(r'^api/v2.1/deleted-repos/$', DeletedRepos.as_view(), name='api2-v2.1-deleted-repos'), url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'), url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'), url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/trash/$', RepoTrash.as_view(), name='api-v2.1-repo-trash'), diff --git a/tests/api/endpoints/test_deleted_repos.py b/tests/api/endpoints/test_deleted_repos.py new file mode 100644 index 0000000000..35f217bb8e --- /dev/null +++ b/tests/api/endpoints/test_deleted_repos.py @@ -0,0 +1,47 @@ +import json + +from django.core.urlresolvers import reverse +from seaserv import seafile_api + +from seahub.test_utils import BaseTestCase +from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email + + +class DeletedReposTest(BaseTestCase): + + def test_get_deleted_repos(self): + self.login_as(self.user) + name = self.user.username + repoid = self.create_repo(name='test-repo', desc='', + username=name, + passwd=None) + repo = seafile_api.get_repo(repoid) + self.remove_repo(repoid) + + trashs = self.client.get(reverse("api2-v2.1-deleted-repos")) + json_trashs = json.loads(trashs.content) + json_trashs = [trash for trash in json_trashs if trash['repo_id'] == repo.id] + assert json_trashs[0]['repo_id'] == repo.id + assert json_trashs[0]['owner_email'] == name + assert json_trashs[0]['owner_name'] == email2nickname(name) + assert json_trashs[0]['owner_contact_email'] == email2contact_email(name) + assert json_trashs[0]['repo_name'] == repo.name + #assert json_trashs[0]['org_id'] == repo.org_id + assert json_trashs[0]['size'] == repo.size + self.assertIsNotNone(json_trashs[0]['head_commit_id']) + self.assertIsNotNone(json_trashs[0]['del_time']) + #self.assertIsNotNone(json_trashs[0]['encrypted']) + + def test_can_restore_deleted_repos(self): + self.login_as(self.user) + name = self.user.username + repoid = self.create_repo(name='test-repo', desc='', + username=name, + passwd=None) + remove_status = self.remove_repo(repoid) + assert remove_status == 0 + response = self.client.post( + reverse("api2-v2.1-deleted-repos"), + {"repo_id": repoid} + ) + self.assertEqual(response.status_code, 200) From 735faec773da5444298f850c73389a68b002e6c3 Mon Sep 17 00:00:00 2001 From: llj Date: Fri, 23 Jun 2017 12:02:03 +0800 Subject: [PATCH 2/3] [deleted libs] list deleted libraries, and enable user to restore a library --- media/css/seahub.css | 4 + seahub/templates/js/templates.html | 55 +++++++-- seahub/templates/libraries.html | 31 +++++- .../scripts/app/collections/deleted-repos.js | 18 +++ static/scripts/app/models/deleted-repo.js | 30 +++++ static/scripts/app/router.js | 13 ++- static/scripts/app/views/deleted-repo.js | 72 ++++++++++++ static/scripts/app/views/my-deleted-repos.js | 105 ++++++++++++++++++ static/scripts/app/views/myhome-repos.js | 17 ++- static/scripts/common.js | 1 + 10 files changed, 332 insertions(+), 14 deletions(-) create mode 100644 static/scripts/app/collections/deleted-repos.js create mode 100644 static/scripts/app/models/deleted-repo.js create mode 100644 static/scripts/app/views/deleted-repo.js create mode 100644 static/scripts/app/views/my-deleted-repos.js diff --git a/media/css/seahub.css b/media/css/seahub.css index 8e90f13ecf..943b70e685 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -117,6 +117,7 @@ .icon-eye-slash:before { content: "\f070"; } .icon-plus-square:before { content: "\f0fe"; } .icon-envelope:before { content: "\f0e0"; } +.icon-ellipsis-vertical:before { content: "\f142"; } .fa-1x { font-size: 1.3em; } @@ -1788,6 +1789,9 @@ button.sf-dropdown-toggle:focus { background:#fff; line-height:17px; } +.more-op-btn-white { + width:29px; +} /* info-bar */ #info-bar { color:#1f0600; diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 723d0cfa46..9fa315d0da 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -154,6 +154,30 @@ + + + + + + + + +