mirror of
https://github.com/haiwen/seahub.git
synced 2025-10-21 10:51:17 +00:00
rm expire invitations
This commit is contained in:
27
seahub/api2/endpoints/admin/invitations.py
Normal file
27
seahub/api2/endpoints/admin/invitations.py
Normal 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)
|
@@ -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')),
|
||||
|
@@ -4,16 +4,22 @@
|
||||
{% block cur_invitations %}tab-cur{% endblock %}
|
||||
|
||||
{% 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 %}
|
||||
<table>
|
||||
<tr>
|
||||
<th width="25%">{% trans "Inviter" %}</th>
|
||||
<th width="25%">{% trans "Accepter" %}</th>
|
||||
<th width="10%">{% trans "Type" %}</th>
|
||||
<th width="16%">{% trans "Invited at" %}</th>
|
||||
<th width="16%">{% trans "Accepted at" %}</th>
|
||||
<th width="20%">{% trans "Inviter" %}</th>
|
||||
<th width="20%">{% trans "Accepter" %}</th>
|
||||
<th width="9%">{% trans "Type" %}</th>
|
||||
<th width="14%">{% trans "Invited at" %}</th>
|
||||
<th width="14%">{% trans "Accepted at" %}</th>
|
||||
<th width="18%">{% trans "Expired at" %}</th>
|
||||
<th width="8%"></th>
|
||||
</tr>
|
||||
{% for invitation in invitations %}
|
||||
@@ -31,6 +37,7 @@
|
||||
{% else %}
|
||||
<td>--</td>
|
||||
{% endif %}
|
||||
<td>{{ invitation.expire_time }}</td>
|
||||
<td><a class="op vh rm-link" href="#" data-id="{{invitation.pk}}">{% trans "Delete" %}</a></td>
|
||||
</tr>
|
||||
{% 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');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -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<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
|
||||
url(r'^api/v2.1/user-avatar/$', UserAvatarView.as_view(), name='api-v2.1-user-avatar'),
|
||||
|
44
tests/api/endpoints/admin/test_invitations.py
Normal file
44
tests/api/endpoints/admin/test_invitations.py
Normal 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()
|
Reference in New Issue
Block a user