1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-10-22 03:16:34 +00:00

rm expire invitations

This commit is contained in:
zming
2017-07-10 15:38:02 +08:00
parent 66f8451011
commit f51d8122e9
5 changed files with 111 additions and 7 deletions

View File

@@ -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)

View File

@@ -18,7 +18,7 @@ GUEST = _('Guest')
class InvitationManager(models.Manager): class InvitationManager(models.Manager):
def add(self, inviter, accepter, invite_type=GUEST): def add(self, inviter, accepter, invite_type=GUEST):
token = gen_token(max_length=32) 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, i = self.model(token=token, inviter=inviter, accepter=accepter,
invite_type=invite_type, expire_time=expire_at) invite_type=invite_type, expire_time=expire_at)
@@ -29,6 +29,9 @@ class InvitationManager(models.Manager):
return super(InvitationManager, return super(InvitationManager,
self).filter(inviter=inviter).order_by('-invite_time') 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): class Invitation(models.Model):
INVITE_TYPE_CHOICES = ( INVITE_TYPE_CHOICES = (
(GUEST, _('Guest')), (GUEST, _('Guest')),

View File

@@ -4,16 +4,22 @@
{% block cur_invitations %}tab-cur{% endblock %} {% block cur_invitations %}tab-cur{% endblock %}
{% block right_panel %} {% block right_panel %}
<h3 class="hd">{% trans "All Invitations" %}</h3>
<div class="hd ovhd">
<h3 class="fleft">{% trans "All Invitations" %}</h3>
<button id="rm-expire-invitations" class="fright btn-white">{% trans "Delete Expired Invitations" %}</button>
</div>
{% if invitations %} {% if invitations %}
<table> <table>
<tr> <tr>
<th width="25%">{% trans "Inviter" %}</th> <th width="20%">{% trans "Inviter" %}</th>
<th width="25%">{% trans "Accepter" %}</th> <th width="20%">{% trans "Accepter" %}</th>
<th width="10%">{% trans "Type" %}</th> <th width="9%">{% trans "Type" %}</th>
<th width="16%">{% trans "Invited at" %}</th> <th width="14%">{% trans "Invited at" %}</th>
<th width="16%">{% trans "Accepted at" %}</th> <th width="14%">{% trans "Accepted at" %}</th>
<th width="18%">{% trans "Expired at" %}</th>
<th width="8%"></th> <th width="8%"></th>
</tr> </tr>
{% for invitation in invitations %} {% for invitation in invitations %}
@@ -31,6 +37,7 @@
{% else %} {% else %}
<td>--</td> <td>--</td>
{% endif %} {% endif %}
<td>{{ invitation.expire_time }}</td>
<td><a class="op vh rm-link" href="#" data-id="{{invitation.pk}}">{% trans "Delete" %}</a></td> <td><a class="op vh rm-link" href="#" data-id="{{invitation.pk}}">{% trans "Delete" %}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
@@ -62,5 +69,26 @@ $('.rm-link').click(function() {
}); });
return false; 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');
}
});
});
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -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.copy_move_task import CopyMoveTaskView
from seahub.api2.endpoints.query_copy_move_progress import QueryCopyMoveProgressView from seahub.api2.endpoints.query_copy_move_progress import QueryCopyMoveProgressView
from seahub.api2.endpoints.invitations import InvitationsView 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.invitation import InvitationView
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView from seahub.api2.endpoints.notifications import NotificationsView, NotificationView
from seahub.api2.endpoints.user_enabled_modules import UserEnabledModulesView from seahub.api2.endpoints.user_enabled_modules import UserEnabledModulesView
@@ -234,6 +235,7 @@ urlpatterns = patterns(
## user::invitations ## user::invitations
url(r'^api/v2.1/invitations/$', InvitationsView.as_view()), url(r'^api/v2.1/invitations/$', InvitationsView.as_view()),
url(r'^api/v2.1/invitations/(?P<token>[a-f0-9]{32})/$', InvitationView.as_view()), url(r'^api/v2.1/invitations/(?P<token>[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 ## user::avatar
url(r'^api/v2.1/user-avatar/$', UserAvatarView.as_view(), name='api-v2.1-user-avatar'), url(r'^api/v2.1/user-avatar/$', UserAvatarView.as_view(), name='api-v2.1-user-avatar'),

View File

@@ -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()