diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d0e02cc130..46928ff101 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,7 +14,7 @@ "@gatsbyjs/reach-router": "1.3.9", "@seafile/react-image-lightbox": "2.0.2", "@seafile/resumablejs": "1.1.16", - "@seafile/sdoc-editor": "0.5.63", + "@seafile/sdoc-editor": "0.5.64", "@seafile/seafile-calendar": "0.0.12", "@seafile/seafile-editor": "1.0.82", "@uiw/codemirror-extensions-langs": "^4.19.4", @@ -4617,9 +4617,9 @@ "integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig==" }, "node_modules/@seafile/sdoc-editor": { - "version": "0.5.63", - "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.63.tgz", - "integrity": "sha512-qXi1VOSSfREtsVwdVSj7brLhsqIc7+rxBX8WHQlioUmSvv53xd/RBFJRtmla9Ui+LvmyCSGtzZ4oTKZU2/WAGA==", + "version": "0.5.64", + "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.64.tgz", + "integrity": "sha512-kDZwJEprBvvo8qCsaEh4zoPJLsKkg5d9co20buJ20raMDTd3IH/iuylj4Pp3hEyiSUFeT4zwOdxMFV2Vr1a+UQ==", "dependencies": { "@seafile/print-js": "1.6.5", "@seafile/react-image-lightbox": "2.0.4", @@ -31292,9 +31292,9 @@ "integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig==" }, "@seafile/sdoc-editor": { - "version": "0.5.63", - "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.63.tgz", - "integrity": "sha512-qXi1VOSSfREtsVwdVSj7brLhsqIc7+rxBX8WHQlioUmSvv53xd/RBFJRtmla9Ui+LvmyCSGtzZ4oTKZU2/WAGA==", + "version": "0.5.64", + "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.64.tgz", + "integrity": "sha512-kDZwJEprBvvo8qCsaEh4zoPJLsKkg5d9co20buJ20raMDTd3IH/iuylj4Pp3hEyiSUFeT4zwOdxMFV2Vr1a+UQ==", "requires": { "@seafile/print-js": "1.6.5", "@seafile/react-image-lightbox": "2.0.4", diff --git a/frontend/package.json b/frontend/package.json index ec4e521f33..f6fceede84 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,7 +9,7 @@ "@gatsbyjs/reach-router": "1.3.9", "@seafile/react-image-lightbox": "2.0.2", "@seafile/resumablejs": "1.1.16", - "@seafile/sdoc-editor": "0.5.63", + "@seafile/sdoc-editor": "0.5.64", "@seafile/seafile-calendar": "0.0.12", "@seafile/seafile-editor": "1.0.82", "@uiw/codemirror-extensions-langs": "^4.19.4", diff --git a/seahub/adfs_auth/views.py b/seahub/adfs_auth/views.py index 1edbc25ee2..bd5fdc1422 100644 --- a/seahub/adfs_auth/views.py +++ b/seahub/adfs_auth/views.py @@ -29,6 +29,7 @@ from saml2.client import Saml2Client from saml2.metadata import entity_descriptor from djangosaml2.cache import IdentityCache, OutstandingQueriesCache from djangosaml2.conf import get_config +from djangosaml2.views import LogoutView from seaserv import ccnet_api, seafile_api @@ -562,3 +563,7 @@ def adfs_compatible_view(request, url_prefix): org_id = str(org.org_id) return HttpResponsePermanentRedirect(request.path.replace(url_prefix, org_id)) + +class SamlLogoutView(LogoutView): + def do_logout_service(self, request, data, binding, *args, **kwargs): + return super(SamlLogoutView, self).do_logout_service(request, data, binding) diff --git a/seahub/two_factor/views/login.py b/seahub/two_factor/views/login.py index 7e0a847144..acc6deac17 100644 --- a/seahub/two_factor/views/login.py +++ b/seahub/two_factor/views/login.py @@ -1,45 +1,32 @@ # Copyright (c) 2012-2016 Seafile Ltd. -import hashlib -import re import logging -from datetime import datetime from importlib import import_module +from formtools.wizard.views import SessionWizardView from constance import config from django.conf import settings from django.urls import reverse -from django.http import HttpResponseRedirect, Http404 -from django.utils.translation import gettext as _ +from django.http import HttpResponseRedirect from django.views.decorators.cache import never_cache -from django.contrib.sites.shortcuts import get_current_site from django.shortcuts import redirect from django.utils.http import url_has_allowed_host_and_scheme from django.views.decorators.debug import sensitive_post_parameters -from formtools.wizard.views import SessionWizardView - - from seahub.auth import REDIRECT_FIELD_NAME, get_backends from seahub.auth import login as auth_login from seahub.base.accounts import User -from seahub.utils.ip import get_remote_ip - from seahub.profile.models import Profile - -from seahub.two_factor import login as two_factor_login -from seahub.two_factor.models import (StaticDevice, TOTPDevice, default_device, - user_has_device) - -from seahub.two_factor.forms import TOTPTokenAuthForm, BackupTokenAuthForm, AuthenticationTokenForm +from seahub.two_factor.models import StaticDevice, default_device, user_has_device +from seahub.two_factor.forms import BackupTokenAuthForm, AuthenticationTokenForm from seahub.two_factor.views.utils import class_view_decorator - from seahub.utils.auth import get_login_bg_image_path # Get an instance of a logger logger = logging.getLogger(__name__) + @class_view_decorator(sensitive_post_parameters()) @class_view_decorator(never_cache) class TwoFactorVerifyView(SessionWizardView): @@ -99,28 +86,29 @@ class TwoFactorVerifyView(SessionWizardView): """ Login the user and redirect to the desired page. """ - redirect_to = self.request.session.get(SESSION_KEY_TWO_FACTOR_REDIRECT_URL, '') \ - or self.request.GET.get(self.redirect_field_name, '') + redirect_to = ( + self.request.session.get(SESSION_KEY_TWO_FACTOR_REDIRECT_URL, '') + or self.request.GET.get(self.redirect_field_name, '') + ) auth_login(self.request, self.user) self.reset_two_factor_session() - if not url_has_allowed_host_and_scheme(url=redirect_to, allowed_hosts=self.request.get_host()): + if not url_has_allowed_host_and_scheme(url=redirect_to, + allowed_hosts=self.request.get_host()): redirect_to = str(settings.LOGIN_REDIRECT_URL) res = HttpResponseRedirect(redirect_to) - if form_list[0].is_valid(): - remember_me = form_list[0].cleaned_data['remember_me'] - if remember_me: - s = remember_device(self.user.username) - res.set_cookie( - 'S2FA', s.session_key, - max_age=settings.TWO_FACTOR_DEVICE_REMEMBER_DAYS * 24 * 60 * 60, - domain=settings.SESSION_COOKIE_DOMAIN, - path=settings.SESSION_COOKIE_PATH, - secure=settings.SESSION_COOKIE_SECURE or None, - httponly=settings.SESSION_COOKIE_HTTPONLY or None) + if kwargs.get('remember_me', False): + s = remember_device(self.user.username) + res.set_cookie( + 'S2FA', s.session_key, + max_age=settings.TWO_FACTOR_DEVICE_REMEMBER_DAYS * 24 * 60 * 60, + domain=settings.SESSION_COOKIE_DOMAIN, + path=settings.SESSION_COOKIE_PATH, + secure=settings.SESSION_COOKIE_SECURE or None, + httponly=settings.SESSION_COOKIE_HTTPONLY or None) return res def get_form_kwargs(self, step=None): @@ -199,22 +187,28 @@ class TwoFactorVerifyView(SessionWizardView): ) final_form_list.append(form_obj) + kwargs['remember_me'] = form.cleaned_data['remember_me'] done_response = self.done(final_form_list, **kwargs) self.storage.reset() return done_response + def two_factor_auth_enabled(user): return config.ENABLE_TWO_FACTOR_AUTH and user_has_device(user) + SESSION_KEY_TWO_FACTOR_AUTH_USERNAME = '2fa-username' SESSION_KEY_TWO_FACTOR_REDIRECT_URL = '2fa-redirect-url' SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT = '2fa-failed-attempt' + + def handle_two_factor_auth(request, user, redirect_to): request.session[SESSION_KEY_TWO_FACTOR_AUTH_USERNAME] = user.username request.session[SESSION_KEY_TWO_FACTOR_REDIRECT_URL] = redirect_to request.session[SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT] = 0 return redirect(reverse('two_factor_auth')) + def verify_two_factor_token(user, token): """ This function is called when doing the api authentication. @@ -225,6 +219,7 @@ def verify_two_factor_token(user, token): if device: return device.verify_token(token) + def remember_device(s_data): SessionStore = import_module(settings.SESSION_ENGINE).SessionStore s = SessionStore() @@ -233,6 +228,7 @@ def remember_device(s_data): s.create() return s + def is_device_remembered(request_header, user): if not request_header: return False diff --git a/seahub/urls.py b/seahub/urls.py index ba563ec93d..4a0175484b 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -942,6 +942,8 @@ if getattr(settings, 'ENABLE_MULTI_ADFS', False): re_path(r'^org/custom/(?P\d+)/saml2/metadata/$', metadata, name='org_saml2_metadata'), re_path(r'^org/custom/(?P\d+)/saml2/connect/$', saml2_connect, name='org_saml2_connect'), re_path(r'^org/custom/(?P\d+)/saml2/disconnect/$', saml2_disconnect, name='org_saml2_disconnect'), + re_path(r'^org/custom/(?P\d+)/saml2/ls/$', SamlLogoutView.as_view(), name='org_saml2_ls'), + re_path(r'^org/custom/(?P\d+)/saml2/ls/post/$', SamlLogoutView.as_view(), name='org_saml2_ls_post'), re_path(r'^org/custom/(?P\d+)/saml2/', include(('djangosaml2.urls', 'djangosaml2'), namespace='org')), re_path(r'^org/custom/(?P[a-z_0-9-]+)/saml2/login/$', adfs_compatible_view, name='login_compatible_view'), re_path(r'^org/custom/(?P[a-z_0-9-]+)/saml2/acs/$', adfs_compatible_view, name='acs_compatible_view'),