From f51d8122e9fc5c0c5f9109767c6817a9a7f3b241 Mon Sep 17 00:00:00 2001 From: zming <517046497@qq.com> Date: Mon, 10 Jul 2017 15:38:02 +0800 Subject: [PATCH] rm expire invitations --- seahub/api2/endpoints/admin/invitations.py | 27 ++++++++++++ seahub/invitations/models.py | 5 ++- .../sysadmin/sys_invitations_admin.html | 40 ++++++++++++++--- seahub/urls.py | 2 + tests/api/endpoints/admin/test_invitations.py | 44 +++++++++++++++++++ 5 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 seahub/api2/endpoints/admin/invitations.py create mode 100644 tests/api/endpoints/admin/test_invitations.py diff --git a/seahub/api2/endpoints/admin/invitations.py b/seahub/api2/endpoints/admin/invitations.py new file mode 100644 index 0000000000..b73b399a65 --- /dev/null +++ b/seahub/api2/endpoints/admin/invitations.py @@ -0,0 +1,27 @@ +# Copyright (c) 2012-2016 Seafile Ltd. +from django.contrib import messages +from rest_framework.authentication import SessionAuthentication +from rest_framework.permissions import IsAdminUser +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework import status + +from seahub.api2.authentication import TokenAuthentication +from seahub.api2.throttling import UserRateThrottle +from seahub.api2.utils import api_error +from seahub.invitations.models import Invitation + + +class InvitationsView(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication) + throttle_classes = (UserRateThrottle, ) + permission_classes = (IsAdminUser, ) + + def delete(self, request): + _type = request.GET.get('type', '') + if not _type: + error_msg = "type can not be empty" % _type + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + if _type == "expired": + Invitation.objects.delete_all_expire_invitation() + return Response(status.HTTP_200_OK) diff --git a/seahub/invitations/models.py b/seahub/invitations/models.py index d43d80634d..c87292e6f5 100644 --- a/seahub/invitations/models.py +++ b/seahub/invitations/models.py @@ -18,7 +18,7 @@ GUEST = _('Guest') class InvitationManager(models.Manager): def add(self, inviter, accepter, invite_type=GUEST): token = gen_token(max_length=32) - expire_at = timezone.now() + timedelta(hours=INVITATIONS_TOKEN_AGE) + expire_at = timezone.now() + timedelta(hours=int(INVITATIONS_TOKEN_AGE)) i = self.model(token=token, inviter=inviter, accepter=accepter, invite_type=invite_type, expire_time=expire_at) @@ -29,6 +29,9 @@ class InvitationManager(models.Manager): return super(InvitationManager, self).filter(inviter=inviter).order_by('-invite_time') + def delete_all_expire_invitation(self): + super(InvitationManager, self).filter(expire_time__lte=timezone.now()).delete() + class Invitation(models.Model): INVITE_TYPE_CHOICES = ( (GUEST, _('Guest')), diff --git a/seahub/templates/sysadmin/sys_invitations_admin.html b/seahub/templates/sysadmin/sys_invitations_admin.html index a189d97c13..30af0a69c9 100644 --- a/seahub/templates/sysadmin/sys_invitations_admin.html +++ b/seahub/templates/sysadmin/sys_invitations_admin.html @@ -4,16 +4,22 @@ {% block cur_invitations %}tab-cur{% endblock %} {% block right_panel %} -

{% trans "All Invitations" %}

+ +
+

{% trans "All Invitations" %}

+ + +
{% if invitations %} - - - - - + + + + + + {% for invitation in invitations %} @@ -31,6 +37,7 @@ {% else %} {% endif %} + {% endfor %} @@ -62,5 +69,26 @@ $('.rm-link').click(function() { }); return false; }); +$("#rm-expire-invitations").click(function() { + $.ajax({ + url: '{% url 'api-v2.1-admin-invitations' %}?type=expired', + type: 'DELETE', + cache: false, + dataType: 'json', + beforeSend: prepareCSRFToken, + success: function(data) { + location.reload(true); + }, + error: function(xhr,status,error){ + if (xhr.responseText) { + err_msg = $.parseJSON(xhr.responseText).error||$.parseJSON(xhr.responseText).error_msg; + } else { + err_msg = gettext("Failed. Please check the network."); + } + feedback(err_msg, 'error'); + } + }); +}); + {% endblock %} diff --git a/seahub/urls.py b/seahub/urls.py index a098e45c1c..f2355adf7d 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -39,6 +39,7 @@ from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView from seahub.api2.endpoints.copy_move_task import CopyMoveTaskView from seahub.api2.endpoints.query_copy_move_progress import QueryCopyMoveProgressView from seahub.api2.endpoints.invitations import InvitationsView +from seahub.api2.endpoints.admin.invitations import InvitationsView as AdminInvitationsView from seahub.api2.endpoints.invitation import InvitationView from seahub.api2.endpoints.notifications import NotificationsView, NotificationView from seahub.api2.endpoints.user_enabled_modules import UserEnabledModulesView @@ -234,6 +235,7 @@ urlpatterns = patterns( ## user::invitations url(r'^api/v2.1/invitations/$', InvitationsView.as_view()), url(r'^api/v2.1/invitations/(?P[a-f0-9]{32})/$', InvitationView.as_view()), + url(r'^api/v2.1/admin/invitations/$', AdminInvitationsView.as_view(), name='api-v2.1-admin-invitations'), ## user::avatar url(r'^api/v2.1/user-avatar/$', UserAvatarView.as_view(), name='api-v2.1-user-avatar'), diff --git a/tests/api/endpoints/admin/test_invitations.py b/tests/api/endpoints/admin/test_invitations.py new file mode 100644 index 0000000000..a1eaf32e0d --- /dev/null +++ b/tests/api/endpoints/admin/test_invitations.py @@ -0,0 +1,44 @@ +import time +from mock import patch + +from django.utils import timezone +from django.core.urlresolvers import reverse + +from seahub.test_utils import BaseTestCase +from seahub.invitations.models import Invitation +from seahub.api2.permissions import CanInviteGuest +from seahub.base.accounts import UserPermissions +from seahub.invitations import models + + +class InvitationsTest(BaseTestCase): + def setUp(self): + self.login_as(self.admin) + + @patch.object(CanInviteGuest, 'has_permission') + @patch.object(UserPermissions, 'can_invite_guest') + def test_can_del_all_expired_invitation(self, mock_has_permission, mock_can_invite_guest): + self.login_as(self.admin) + + mock_has_permission = True + mock_can_invite_guest = True + + invitations_number = len(Invitation.objects.all()) + self._add_invitations('test@noway.com') + self._add_invitations('test1@noway.com') + new_invitations_number = len(Invitation.objects.all()) + self.assertEqual(2, new_invitations_number-invitations_number) + + time.sleep(2) + delete_url = reverse('api-v2.1-admin-invitations') + resp = self.client.delete(delete_url+"?type=expired") + self.assertEqual(200, resp.status_code) + self.assertEqual(invitations_number, len(Invitation.objects.all())) + + def _add_invitations(self, email): + entry = models.Invitation(token=models.gen_token(max_length=32), + inviter=self.admin, + accepter=email, + invite_type=models.GUEST, + expire_time=timezone.now()) + entry.save()
{% trans "Inviter" %}{% trans "Accepter" %}{% trans "Type" %}{% trans "Invited at" %}{% trans "Accepted at" %}{% trans "Inviter" %}{% trans "Accepter" %}{% trans "Type" %}{% trans "Invited at" %}{% trans "Accepted at" %}{% trans "Expired at" %}
--{{ invitation.expire_time }} {% trans "Delete" %}