1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-30 21:50:59 +00:00

Merge branch 'master' into 12.0

This commit is contained in:
杨顺强 2024-05-27 10:39:14 +08:00
commit d24d71420e
5 changed files with 43 additions and 40 deletions

View File

@ -14,7 +14,7 @@
"@gatsbyjs/reach-router": "1.3.9", "@gatsbyjs/reach-router": "1.3.9",
"@seafile/react-image-lightbox": "2.0.2", "@seafile/react-image-lightbox": "2.0.2",
"@seafile/resumablejs": "1.1.16", "@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-calendar": "0.0.12",
"@seafile/seafile-editor": "1.0.82", "@seafile/seafile-editor": "1.0.82",
"@uiw/codemirror-extensions-langs": "^4.19.4", "@uiw/codemirror-extensions-langs": "^4.19.4",
@ -4617,9 +4617,9 @@
"integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig==" "integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig=="
}, },
"node_modules/@seafile/sdoc-editor": { "node_modules/@seafile/sdoc-editor": {
"version": "0.5.63", "version": "0.5.64",
"resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.63.tgz", "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.64.tgz",
"integrity": "sha512-qXi1VOSSfREtsVwdVSj7brLhsqIc7+rxBX8WHQlioUmSvv53xd/RBFJRtmla9Ui+LvmyCSGtzZ4oTKZU2/WAGA==", "integrity": "sha512-kDZwJEprBvvo8qCsaEh4zoPJLsKkg5d9co20buJ20raMDTd3IH/iuylj4Pp3hEyiSUFeT4zwOdxMFV2Vr1a+UQ==",
"dependencies": { "dependencies": {
"@seafile/print-js": "1.6.5", "@seafile/print-js": "1.6.5",
"@seafile/react-image-lightbox": "2.0.4", "@seafile/react-image-lightbox": "2.0.4",
@ -31292,9 +31292,9 @@
"integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig==" "integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig=="
}, },
"@seafile/sdoc-editor": { "@seafile/sdoc-editor": {
"version": "0.5.63", "version": "0.5.64",
"resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.63.tgz", "resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-0.5.64.tgz",
"integrity": "sha512-qXi1VOSSfREtsVwdVSj7brLhsqIc7+rxBX8WHQlioUmSvv53xd/RBFJRtmla9Ui+LvmyCSGtzZ4oTKZU2/WAGA==", "integrity": "sha512-kDZwJEprBvvo8qCsaEh4zoPJLsKkg5d9co20buJ20raMDTd3IH/iuylj4Pp3hEyiSUFeT4zwOdxMFV2Vr1a+UQ==",
"requires": { "requires": {
"@seafile/print-js": "1.6.5", "@seafile/print-js": "1.6.5",
"@seafile/react-image-lightbox": "2.0.4", "@seafile/react-image-lightbox": "2.0.4",

View File

@ -9,7 +9,7 @@
"@gatsbyjs/reach-router": "1.3.9", "@gatsbyjs/reach-router": "1.3.9",
"@seafile/react-image-lightbox": "2.0.2", "@seafile/react-image-lightbox": "2.0.2",
"@seafile/resumablejs": "1.1.16", "@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-calendar": "0.0.12",
"@seafile/seafile-editor": "1.0.82", "@seafile/seafile-editor": "1.0.82",
"@uiw/codemirror-extensions-langs": "^4.19.4", "@uiw/codemirror-extensions-langs": "^4.19.4",

View File

@ -29,6 +29,7 @@ from saml2.client import Saml2Client
from saml2.metadata import entity_descriptor from saml2.metadata import entity_descriptor
from djangosaml2.cache import IdentityCache, OutstandingQueriesCache from djangosaml2.cache import IdentityCache, OutstandingQueriesCache
from djangosaml2.conf import get_config from djangosaml2.conf import get_config
from djangosaml2.views import LogoutView
from seaserv import ccnet_api, seafile_api from seaserv import ccnet_api, seafile_api
@ -562,3 +563,7 @@ def adfs_compatible_view(request, url_prefix):
org_id = str(org.org_id) org_id = str(org.org_id)
return HttpResponsePermanentRedirect(request.path.replace(url_prefix, 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)

View File

@ -1,45 +1,32 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
import hashlib
import re
import logging import logging
from datetime import datetime
from importlib import import_module from importlib import import_module
from formtools.wizard.views import SessionWizardView
from constance import config from constance import config
from django.conf import settings from django.conf import settings
from django.urls import reverse from django.urls import reverse
from django.http import HttpResponseRedirect, Http404 from django.http import HttpResponseRedirect
from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache from django.views.decorators.cache import never_cache
from django.contrib.sites.shortcuts import get_current_site
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.http import url_has_allowed_host_and_scheme from django.utils.http import url_has_allowed_host_and_scheme
from django.views.decorators.debug import sensitive_post_parameters 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 REDIRECT_FIELD_NAME, get_backends
from seahub.auth import login as auth_login from seahub.auth import login as auth_login
from seahub.base.accounts import User from seahub.base.accounts import User
from seahub.utils.ip import get_remote_ip
from seahub.profile.models import Profile from seahub.profile.models import Profile
from seahub.two_factor.models import StaticDevice, default_device, user_has_device
from seahub.two_factor import login as two_factor_login from seahub.two_factor.forms import BackupTokenAuthForm, AuthenticationTokenForm
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.views.utils import class_view_decorator from seahub.two_factor.views.utils import class_view_decorator
from seahub.utils.auth import get_login_bg_image_path from seahub.utils.auth import get_login_bg_image_path
# Get an instance of a logger # Get an instance of a logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@class_view_decorator(sensitive_post_parameters()) @class_view_decorator(sensitive_post_parameters())
@class_view_decorator(never_cache) @class_view_decorator(never_cache)
class TwoFactorVerifyView(SessionWizardView): class TwoFactorVerifyView(SessionWizardView):
@ -99,28 +86,29 @@ class TwoFactorVerifyView(SessionWizardView):
""" """
Login the user and redirect to the desired page. Login the user and redirect to the desired page.
""" """
redirect_to = self.request.session.get(SESSION_KEY_TWO_FACTOR_REDIRECT_URL, '') \ redirect_to = (
or self.request.GET.get(self.redirect_field_name, '') 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) auth_login(self.request, self.user)
self.reset_two_factor_session() 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) redirect_to = str(settings.LOGIN_REDIRECT_URL)
res = HttpResponseRedirect(redirect_to) res = HttpResponseRedirect(redirect_to)
if form_list[0].is_valid(): if kwargs.get('remember_me', False):
remember_me = form_list[0].cleaned_data['remember_me'] s = remember_device(self.user.username)
if remember_me: res.set_cookie(
s = remember_device(self.user.username) 'S2FA', s.session_key,
res.set_cookie( max_age=settings.TWO_FACTOR_DEVICE_REMEMBER_DAYS * 24 * 60 * 60,
'S2FA', s.session_key, domain=settings.SESSION_COOKIE_DOMAIN,
max_age=settings.TWO_FACTOR_DEVICE_REMEMBER_DAYS * 24 * 60 * 60, path=settings.SESSION_COOKIE_PATH,
domain=settings.SESSION_COOKIE_DOMAIN, secure=settings.SESSION_COOKIE_SECURE or None,
path=settings.SESSION_COOKIE_PATH, httponly=settings.SESSION_COOKIE_HTTPONLY or None)
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None)
return res return res
def get_form_kwargs(self, step=None): def get_form_kwargs(self, step=None):
@ -199,22 +187,28 @@ class TwoFactorVerifyView(SessionWizardView):
) )
final_form_list.append(form_obj) final_form_list.append(form_obj)
kwargs['remember_me'] = form.cleaned_data['remember_me']
done_response = self.done(final_form_list, **kwargs) done_response = self.done(final_form_list, **kwargs)
self.storage.reset() self.storage.reset()
return done_response return done_response
def two_factor_auth_enabled(user): def two_factor_auth_enabled(user):
return config.ENABLE_TWO_FACTOR_AUTH and user_has_device(user) return config.ENABLE_TWO_FACTOR_AUTH and user_has_device(user)
SESSION_KEY_TWO_FACTOR_AUTH_USERNAME = '2fa-username' SESSION_KEY_TWO_FACTOR_AUTH_USERNAME = '2fa-username'
SESSION_KEY_TWO_FACTOR_REDIRECT_URL = '2fa-redirect-url' SESSION_KEY_TWO_FACTOR_REDIRECT_URL = '2fa-redirect-url'
SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT = '2fa-failed-attempt' SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT = '2fa-failed-attempt'
def handle_two_factor_auth(request, user, redirect_to): 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_AUTH_USERNAME] = user.username
request.session[SESSION_KEY_TWO_FACTOR_REDIRECT_URL] = redirect_to request.session[SESSION_KEY_TWO_FACTOR_REDIRECT_URL] = redirect_to
request.session[SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT] = 0 request.session[SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT] = 0
return redirect(reverse('two_factor_auth')) return redirect(reverse('two_factor_auth'))
def verify_two_factor_token(user, token): def verify_two_factor_token(user, token):
""" """
This function is called when doing the api authentication. This function is called when doing the api authentication.
@ -225,6 +219,7 @@ def verify_two_factor_token(user, token):
if device: if device:
return device.verify_token(token) return device.verify_token(token)
def remember_device(s_data): def remember_device(s_data):
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
s = SessionStore() s = SessionStore()
@ -233,6 +228,7 @@ def remember_device(s_data):
s.create() s.create()
return s return s
def is_device_remembered(request_header, user): def is_device_remembered(request_header, user):
if not request_header: if not request_header:
return False return False

View File

@ -942,6 +942,8 @@ if getattr(settings, 'ENABLE_MULTI_ADFS', False):
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/metadata/$', metadata, name='org_saml2_metadata'), re_path(r'^org/custom/(?P<org_id>\d+)/saml2/metadata/$', metadata, name='org_saml2_metadata'),
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/connect/$', saml2_connect, name='org_saml2_connect'), re_path(r'^org/custom/(?P<org_id>\d+)/saml2/connect/$', saml2_connect, name='org_saml2_connect'),
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/disconnect/$', saml2_disconnect, name='org_saml2_disconnect'), re_path(r'^org/custom/(?P<org_id>\d+)/saml2/disconnect/$', saml2_disconnect, name='org_saml2_disconnect'),
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/ls/$', SamlLogoutView.as_view(), name='org_saml2_ls'),
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/ls/post/$', SamlLogoutView.as_view(), name='org_saml2_ls_post'),
re_path(r'^org/custom/(?P<org_id>\d+)/saml2/', include(('djangosaml2.urls', 'djangosaml2'), namespace='org')), re_path(r'^org/custom/(?P<org_id>\d+)/saml2/', include(('djangosaml2.urls', 'djangosaml2'), namespace='org')),
re_path(r'^org/custom/(?P<url_prefix>[a-z_0-9-]+)/saml2/login/$', adfs_compatible_view, name='login_compatible_view'), re_path(r'^org/custom/(?P<url_prefix>[a-z_0-9-]+)/saml2/login/$', adfs_compatible_view, name='login_compatible_view'),
re_path(r'^org/custom/(?P<url_prefix>[a-z_0-9-]+)/saml2/acs/$', adfs_compatible_view, name='acs_compatible_view'), re_path(r'^org/custom/(?P<url_prefix>[a-z_0-9-]+)/saml2/acs/$', adfs_compatible_view, name='acs_compatible_view'),