diff --git a/seahub/api2/endpoints/invitations.py b/seahub/api2/endpoints/invitations.py index 3927b12d94..3e48c88550 100644 --- a/seahub/api2/endpoints/invitations.py +++ b/seahub/api2/endpoints/invitations.py @@ -18,7 +18,7 @@ json_content_type = 'application/json; charset=utf-8' class InvitationsView(APIView): authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated, CanInviteGuest) - throttle_classes = (UserRateThrottle, ) + throttle_classes = (UserRateThrottle,) def get(self, request, format=None): # List invitations sent by user. diff --git a/seahub/api2/permissions.py b/seahub/api2/permissions.py index 5d030906a2..9518cbd05f 100644 --- a/seahub/api2/permissions.py +++ b/seahub/api2/permissions.py @@ -4,6 +4,8 @@ Provides a set of pluggable permission policies. from rest_framework.permissions import BasePermission +from django.conf import settings + from seaserv import check_permission, is_repo_owner, ccnet_api SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'] @@ -59,4 +61,5 @@ class CanInviteGuest(BasePermission): """Check user has permission to invite a guest. """ def has_permission(self, request, *args, **kwargs): - return request.user.permissions.can_invite_guest() + return settings.ENABLE_GUEST_INVITATION and \ + request.user.permissions.can_invite_guest() diff --git a/seahub/base/context_processors.py b/seahub/base/context_processors.py index 8a41e587ab..f2766a3ca9 100644 --- a/seahub/base/context_processors.py +++ b/seahub/base/context_processors.py @@ -14,7 +14,7 @@ from constance import config from seahub.settings import SEAFILE_VERSION, SITE_TITLE, SITE_NAME, \ MAX_FILE_NAME, BRANDING_CSS, LOGO_PATH, LOGO_WIDTH, LOGO_HEIGHT,\ - SHOW_REPO_DOWNLOAD_BUTTON, SITE_ROOT + SHOW_REPO_DOWNLOAD_BUTTON, SITE_ROOT, ENABLE_GUEST_INVITATION try: from seahub.settings import SEACLOUD_MODE @@ -82,4 +82,5 @@ def base(request): 'SITE_ROOT': SITE_ROOT, 'constance_enabled': dj_settings.CONSTANCE_ENABLED, 'FILE_SERVER_ROOT': file_server_root, + 'enable_guest_invitation': ENABLE_GUEST_INVITATION, } diff --git a/seahub/settings.py b/seahub/settings.py index 4e0bbe6f3e..c3be3bdae1 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -528,6 +528,8 @@ ENABLED_ROLE_PERMISSIONS = { }, } +ENABLE_GUEST_INVITATION = False + ##################### # Sudo Mode # ##################### diff --git a/seahub/templates/home_base.html b/seahub/templates/home_base.html index a0920e51ab..5fd4f09839 100644 --- a/seahub/templates/home_base.html +++ b/seahub/templates/home_base.html @@ -45,7 +45,7 @@ {% endif %} {% endfor %}
  • {% trans "Linked Devices" %}
  • - {% if user.permissions.can_invite_guest %} + {% if enable_guest_invitation and user.permissions.can_invite_guest %}
  • {% trans "Invite People" %}
  • diff --git a/seahub/templates/js/sysadmin-templates.html b/seahub/templates/js/sysadmin-templates.html index 60acc197df..7fd2dec1b6 100644 --- a/seahub/templates/js/sysadmin-templates.html +++ b/seahub/templates/js/sysadmin-templates.html @@ -56,9 +56,11 @@ {% trans "Virus Scan" %} {% endif %} + {% if enable_guest_invitation %}
  • {% trans "Invitations" %}
  • + {% endif %} <% if (cur_tab == 'libraries') { %> <% if (option == 'all') { %> diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 3ed12a08c6..b75d423076 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -694,7 +694,7 @@
  • {% trans "Linked Devices" %}
  • - {% if user.permissions.can_invite_guest %} + {% if enable_guest_invitation and user.permissions.can_invite_guest %}
  • {% trans "Invite People" %}
  • diff --git a/seahub/templates/sysadmin/base.html b/seahub/templates/sysadmin/base.html index f9fa397a24..9f7f51fba7 100644 --- a/seahub/templates/sysadmin/base.html +++ b/seahub/templates/sysadmin/base.html @@ -62,10 +62,11 @@ {% trans "Virus Scan" %} {% endif %} + {% if enable_guest_invitation %}
  • {% trans "Invitations" %}
  • - + {% endif %} {% endblock %} diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index 128647a2b8..bc002a452f 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -6,7 +6,6 @@ import logging import json import re import datetime -import stat import csv, chardet, StringIO import time from constance import config @@ -38,9 +37,8 @@ from seahub.invitations.models import Invitation from seahub.role_permissions.utils import get_available_roles from seahub.utils import IS_EMAIL_CONFIGURED, string2list, is_valid_username, \ is_pro_version, send_html_email, get_user_traffic_list, get_server_id, \ - clear_token, gen_file_get_url, is_org_context, handle_virus_record, \ - get_virus_record_by_id, get_virus_record, FILE_AUDIT_ENABLED, \ - get_max_upload_file_size + clear_token, handle_virus_record, get_virus_record_by_id, \ + get_virus_record, FILE_AUDIT_ENABLED, get_max_upload_file_size from seahub.utils.file_size import get_file_size_unit from seahub.utils.rpc import mute_seafile_api from seahub.utils.licenseparse import parse_license @@ -51,7 +49,7 @@ from seahub.utils.user_permissions import (get_basic_user_roles, get_user_role) from seahub.views.ajax import (get_related_users_by_org_repo, get_related_users_by_repo) -from seahub.views import get_system_default_repo_id, gen_path_link +from seahub.views import get_system_default_repo_id from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm from seahub.options.models import UserOptions from seahub.profile.models import Profile, DetailedProfile @@ -60,7 +58,7 @@ from seahub.share.models import FileShare, UploadLinkShare import seahub.settings as settings from seahub.settings import INIT_PASSWD, SITE_NAME, SITE_ROOT, \ SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, SEND_EMAIL_ON_RESETTING_USER_PASSWD, \ - ENABLE_SYS_ADMIN_VIEW_REPO + ENABLE_SYS_ADMIN_VIEW_REPO, ENABLE_GUEST_INVITATION try: from seahub.settings import ENABLE_TRIAL_ACCOUNT except: @@ -2247,6 +2245,10 @@ def sys_inst_toggle_admin(request, inst_id, email): def sys_invitation_admin(request): """List all invitations . """ + + if not ENABLE_GUEST_INVITATION: + raise Http404 + # Make sure page request is an int. If not, deliver first page. try: current_page = int(request.GET.get('page', '1')) @@ -2257,7 +2259,7 @@ def sys_invitation_admin(request): offset = per_page * (current_page - 1) limit = per_page + 1 - invitations = Invitation.objects.all()[offset:offset + limit] + invitations = Invitation.objects.all().order_by('-invite_time')[offset:offset + limit] if len(invitations) == per_page + 1: page_next = True diff --git a/static/scripts/app/views/invitations.js b/static/scripts/app/views/invitations.js index 5a5446648c..e610dcf385 100644 --- a/static/scripts/app/views/invitations.js +++ b/static/scripts/app/views/invitations.js @@ -73,7 +73,7 @@ define([ error: function(collection, response, options) { var err_msg; if (response.responseText) { - err_msg = response.responseJSON.error_msg; + err_msg = response.responseJSON.error_msg||response.responseJSON.detail; } else { err_msg = gettext('Please check the network.'); } diff --git a/static/scripts/common.js b/static/scripts/common.js index c25c7979e3..03095b1b9b 100644 --- a/static/scripts/common.js +++ b/static/scripts/common.js @@ -349,7 +349,7 @@ define([ ajaxErrorHandler: function(xhr, textStatus, errorThrown) { if (xhr.responseText) { var parsed_resp = $.parseJSON(xhr.responseText); - this.feedback(parsed_resp.error||parsed_resp.error_msg, 'error'); + this.feedback(parsed_resp.error||parsed_resp.error_msg||parsed_resp.detail, 'error'); } else { this.feedback(gettext("Failed. Please check the network."), 'error'); } diff --git a/tests/api/endpoints/test_invitation.py b/tests/api/endpoints/test_invitation.py index 24d6db1b19..f748e3f6be 100644 --- a/tests/api/endpoints/test_invitation.py +++ b/tests/api/endpoints/test_invitation.py @@ -1,11 +1,10 @@ import json from mock import patch -from django.core.urlresolvers import reverse - from seahub.base.accounts import UserPermissions from seahub.invitations.models import Invitation from seahub.test_utils import BaseTestCase +from seahub.api2.permissions import CanInviteGuest class InvitationsTest(BaseTestCase): @@ -18,9 +17,12 @@ class InvitationsTest(BaseTestCase): self.endpoint = '/api/v2.1/invitations/' + self.i.token + '/' assert len(Invitation.objects.all()) == 1 + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_can_get_one(self, mock_can_invite_guest): + def test_can_get_one(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True resp = self.client.get(self.endpoint) self.assertEqual(200, resp.status_code) @@ -29,9 +31,12 @@ class InvitationsTest(BaseTestCase): assert json_resp['inviter'] == self.username assert json_resp['accepter'] == '1@1.com' + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_get_invalid(self, mock_can_invite_guest): + def test_get_invalid(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True self.i.delete() assert len(Invitation.objects.all()) == 0 @@ -39,9 +44,12 @@ class InvitationsTest(BaseTestCase): resp = self.client.get(self.endpoint) self.assertEqual(404, resp.status_code) + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_get_permission_denied(self, mock_can_invite_guest): + def test_get_permission_denied(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True self.logout() self.login_as(self.admin) @@ -50,9 +58,12 @@ class InvitationsTest(BaseTestCase): self.assertEqual(403, resp.status_code) self.logout() + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_can_delete(self, mock_can_invite_guest): + def test_can_delete(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True resp = self.client.delete(self.endpoint) self.assertEqual(204, resp.status_code) diff --git a/tests/api/endpoints/test_invitations.py b/tests/api/endpoints/test_invitations.py index 8b89b9b5d1..4e53c1ecc6 100644 --- a/tests/api/endpoints/test_invitations.py +++ b/tests/api/endpoints/test_invitations.py @@ -2,11 +2,11 @@ import json from mock import patch from post_office.models import Email -from django.core.urlresolvers import reverse from seahub.base.accounts import UserPermissions from seahub.invitations.models import Invitation from seahub.test_utils import BaseTestCase +from seahub.api2.permissions import CanInviteGuest class InvitationsTest(BaseTestCase): def setUp(self): @@ -14,9 +14,12 @@ class InvitationsTest(BaseTestCase): self.endpoint = '/api/v2.1/invitations/' self.username = self.user.username + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_can_add(self, mock_can_invite_guest): + def test_can_add(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True assert len(Invitation.objects.all()) == 0 resp = self.client.post(self.endpoint, { @@ -32,9 +35,12 @@ class InvitationsTest(BaseTestCase): assert len(Invitation.objects.all()) == 1 + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_can_send_mail(self, mock_can_invite_guest): + def test_can_send_mail(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True self.assertEqual(len(Email.objects.all()), 0) @@ -49,9 +55,12 @@ class InvitationsTest(BaseTestCase): self.assertRegexpMatches(Email.objects.all()[0].html_message, json_resp['token']) + @patch.object(CanInviteGuest, 'has_permission') @patch.object(UserPermissions, 'can_invite_guest') - def test_can_list(self, mock_can_invite_guest): + def test_can_list(self, mock_can_invite_guest, mock_has_permission): + mock_can_invite_guest.return_val = True + mock_has_permission.return_val = True Invitation.objects.add(inviter=self.username, accepter='1@1.com') Invitation.objects.add(inviter=self.username, accepter='1@2.com')