1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-04 16:31:13 +00:00

two-factor-auth

This commit is contained in:
zming
2017-07-09 03:14:23 +08:00
parent 66f8451011
commit c2873b9112
5 changed files with 116 additions and 1 deletions

View File

@@ -0,0 +1,34 @@
# Copyright (c) 2012-2016 Seafile Ltd.
from rest_framework import status
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
from rest_framework.response import Response
from seahub.base.accounts import User
from seahub.api2.base import APIView
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import json_response, api_error
from seahub.api2.authentication import TokenAuthentication
from seahub.utils.two_factor_auth import has_two_factor_auth, two_factor_auth_enabled
from seahub_extra.two_factor import devices_for_user
class TwoFactorAuthView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
throttle_classes = (UserRateThrottle,)
permission_classes = (IsAdminUser,)
def delete(self, request, email):
if not email:
error_msg = "email can not be empty"
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
try:
_user = User.objects.get(email=email)
except User.DoesNotExist:
error_msg = "User %s not found" % email
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
devices = devices_for_user(_user)
if devices:
for device in devices:
device.delete()
return Response({'success':True}, status=status.HTTP_200_OK)

View File

@@ -4,6 +4,7 @@ from django.conf.urls import patterns, url, include
from .views import *
from .views_misc import ServerInfoView
from .views_auth import LogoutDeviceView, ClientLoginTokenView
from .endpoints.admin.two_factor_auth import TwoFactorAuthView
from .endpoints.dir_shared_items import DirSharedItemsEndpoint
from .endpoints.account import Account
from .endpoints.shared_upload_links import SharedUploadLinksView
@@ -24,6 +25,7 @@ urlpatterns = patterns('',
url(r'^server-info/$', ServerInfoView.as_view()),
url(r'^logout-device/$', LogoutDeviceView.as_view()),
url(r'^client-login/$', ClientLoginTokenView.as_view()),
url(r'^two-factor-auth/(?P<email>\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/$', TwoFactorAuthView.as_view(), name="two-factor-auth-view"),
url(r'^device-wiped/$', RemoteWipeReportView.as_view()),
url(r'^wopi/', include('seahub.wopi.urls')),

View File

@@ -94,6 +94,17 @@
</span>
<span id="set-quota" title="{% trans "Edit Quota" %}" class="sf2-icon-edit op-icon"></span>
</dd>
<dt>{% trans "Two-Factor Authentication" %}</dt>
<dd id="factor">
{% if two_factor_auth_enabled and default_device %}
<button type="button" id="disable_auth">Disable Two Factor Auth</button>
{% else %}
<button type="button" style="color:#AAA"disabled="disabled">Disable Two Factor Auth</button>
{% endif %}
<p class="error hide"></p>
</dd>
</dl>
<form id="set-name-form" method="post" action="" class="hide">{% csrf_token %}
@@ -331,6 +342,28 @@ $('#set-quota').click(function() {
$("#set-quota-form").modal({appendTo: "#main"});
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
});
$("#disable_auth").click(function(){
var email = "{{ email }}";
var $error = $('.error', $("#factor"));
$.ajax({
url: '{% url 'two-factor-auth-view' email %}',
type: 'DELETE',
cache: false,
beforeSend: prepareCSRFToken,
success:function(data){
location.reload(true);
},
error: function(xhr, textStatus, errorThrown) {
var err_msg;
if (xhr.responseText) {
err_msg = $.parseJSON(xhr.responseText).error_msg;
} else {
err_msg = "{% trans "Failed. Please check the network." %}";
}
$error.html(err_msg).show();
}
})
})
$('#set-name-form').submit(function() {
var nickname = $.trim($('[name="nickname"]', $(this)).val());

View File

@@ -76,7 +76,7 @@ try:
from seahub.settings import MULTI_TENANCY
except ImportError:
MULTI_TENANCY = False
from seahub.utils.two_factor_auth import HAS_TWO_FACTOR_AUTH
from seahub.utils.two_factor_auth import has_two_factor_auth, HAS_TWO_FACTOR_AUTH
from termsandconditions.models import TermsAndConditions
logger = logging.getLogger(__name__)
@@ -618,6 +618,13 @@ def user_info(request, email):
else:
g.role = _('Member')
_default_device = False
_has_two_factor_auth = has_two_factor_auth()
if _has_two_factor_auth:
from seahub_extra.two_factor.utils import default_device
_user = User.objects.get(email=email)
_default_device = default_device(_user)
return render_to_response(
'sysadmin/userinfo.html', {
'owned_repos': owned_repos,
@@ -631,6 +638,8 @@ def user_info(request, email):
'user_shared_links': user_shared_links,
'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO,
'personal_groups': personal_groups,
'two_factor_auth_enabled': _has_two_factor_auth,
'default_device': _default_device,
}, context_instance=RequestContext(request))
@login_required_ajax

View File

@@ -0,0 +1,37 @@
from django.core.urlresolvers import reverse
from seahub.test_utils import BaseTestCase
from seahub_extra.two_factor import devices_for_user
from seahub_extra.two_factor.models import (StaticDevice, TOTPDevice,
PhoneDevice)
class TwoFactorAuthViewTest(BaseTestCase):
def setUp(self):
self.login_as(self.admin)
def test_can_disable_two_factor_auth(self):
totp = TOTPDevice(user=self.admin, name="", confirmed=1)
totp.save()
devices = devices_for_user(self.admin)
i = 0
for device in devices_for_user(self.admin):
if device:
i+=1
assert i > 0
resp = self.client.delete(reverse('two-factor-auth-view', args=[str(self.admin.username)]))
assert resp.status_code == 200
i = 0
for device in devices_for_user(self.admin):
if device:
i+=1
assert i == 0
def tearDown(self):
try:
for device in devices_for_user(self.admin):
device.delete()
except:
pass