mirror of https://github.com/jumpserver/jumpserver
				
				
				
			
						commit
						89496baae5
					
				| 
						 | 
				
			
			@ -30,7 +30,7 @@ class JMSCSVRender(BaseRenderer):
 | 
			
		|||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _gen_table(data, fields):
 | 
			
		||||
        data = data[:100]
 | 
			
		||||
        data = data[:10000]
 | 
			
		||||
        yield ['*{}'.format(f.label) if f.required else f.label for f in fields]
 | 
			
		||||
 | 
			
		||||
        for item in data:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,3 +10,7 @@ class HttpResponseTemporaryRedirect(HttpResponse):
 | 
			
		|||
    def __init__(self, redirect_to):
 | 
			
		||||
        HttpResponse.__init__(self)
 | 
			
		||||
        self['Location'] = iri_to_uri(redirect_to)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_remote_addr(request):
 | 
			
		||||
    return request.META.get("HTTP_X_FORWARDED_HOST") or request.META.get("REMOTE_ADDR")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,6 +86,8 @@ TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS
 | 
			
		|||
ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL
 | 
			
		||||
WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
 | 
			
		||||
 | 
			
		||||
AUTH_EXPIRED_SECONDS = 60 * 5
 | 
			
		||||
 | 
			
		||||
# XPACK
 | 
			
		||||
XPACK_LICENSE_IS_VALID = DYNAMIC.XPACK_LICENSE_IS_VALID
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,8 @@ import re
 | 
			
		|||
import pyotp
 | 
			
		||||
import base64
 | 
			
		||||
import logging
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from django.http import Http404
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
from django.core.cache import cache
 | 
			
		||||
| 
						 | 
				
			
			@ -333,3 +333,15 @@ def get_source_choices():
 | 
			
		|||
    if settings.AUTH_CAS:
 | 
			
		||||
        choices.append((User.SOURCE_CAS, choices_all[User.SOURCE_CAS]))
 | 
			
		||||
    return choices
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_auth_time_valid(session, key):
 | 
			
		||||
    return True if session.get(key, 0) > time.time() else False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_auth_password_time_valid(session):
 | 
			
		||||
    return is_auth_time_valid(session, 'auth_password_expired_at')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_auth_otp_time_valid(session):
 | 
			
		||||
    return is_auth_time_valid(session, 'auth_opt_expired_at')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
# ~*~ coding: utf-8 ~*~
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from django.urls import reverse_lazy, reverse
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
| 
						 | 
				
			
			@ -6,13 +7,17 @@ from django.views.generic.base import TemplateView
 | 
			
		|||
from django.views.generic.edit import FormView
 | 
			
		||||
from django.contrib.auth import logout as auth_logout
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.http.response import HttpResponseForbidden
 | 
			
		||||
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
from authentication.mixins import AuthMixin
 | 
			
		||||
from users.models import User
 | 
			
		||||
from common.utils import get_logger, get_object_or_none
 | 
			
		||||
from common.permissions import IsValidUser
 | 
			
		||||
from ... import forms
 | 
			
		||||
from .password import UserVerifyPasswordView
 | 
			
		||||
from ...utils import (
 | 
			
		||||
    generate_otp_uri, check_otp_code, get_user_or_pre_auth_user,
 | 
			
		||||
    is_auth_password_time_valid, is_auth_otp_time_valid
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
| 
						 | 
				
			
			@ -46,11 +51,50 @@ class UserOtpEnableInstallAppView(TemplateView):
 | 
			
		|||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserOtpEnableBindView(TemplateView, FormView):
 | 
			
		||||
class UserOtpEnableBindView(AuthMixin, TemplateView, FormView):
 | 
			
		||||
    template_name = 'users/user_otp_enable_bind.html'
 | 
			
		||||
    form_class = forms.UserCheckOtpCodeForm
 | 
			
		||||
    success_url = reverse_lazy('authentication:user-otp-settings-success')
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        if self._check_can_bind():
 | 
			
		||||
            return super().get(request, *args, **kwargs)
 | 
			
		||||
        return HttpResponseForbidden()
 | 
			
		||||
 | 
			
		||||
    def post(self, request, *args, **kwargs):
 | 
			
		||||
        if self._check_can_bind():
 | 
			
		||||
            return super().post(request, *args, **kwargs)
 | 
			
		||||
        return HttpResponseForbidden()
 | 
			
		||||
 | 
			
		||||
    def _check_authenticated_user_can_bind(self):
 | 
			
		||||
        user = self.request.user
 | 
			
		||||
        session = self.request.session
 | 
			
		||||
 | 
			
		||||
        if not user.mfa_enabled:
 | 
			
		||||
            return is_auth_password_time_valid(session)
 | 
			
		||||
 | 
			
		||||
        if not user.otp_secret_key:
 | 
			
		||||
            return is_auth_password_time_valid(session)
 | 
			
		||||
 | 
			
		||||
        return is_auth_otp_time_valid(session)
 | 
			
		||||
 | 
			
		||||
    def _check_unauthenticated_user_can_bind(self):
 | 
			
		||||
        session_user = None
 | 
			
		||||
        if not self.request.session.is_empty():
 | 
			
		||||
            user_id = self.request.session.get('user_id')
 | 
			
		||||
            session_user = get_object_or_none(User, pk=user_id)
 | 
			
		||||
 | 
			
		||||
        if session_user:
 | 
			
		||||
            if all((is_auth_password_time_valid(self.request.session), session_user.mfa_enabled, not session_user.otp_secret_key)):
 | 
			
		||||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def _check_can_bind(self):
 | 
			
		||||
        if self.request.user.is_authenticated:
 | 
			
		||||
            return self._check_authenticated_user_can_bind()
 | 
			
		||||
        else:
 | 
			
		||||
            return self._check_unauthenticated_user_can_bind()
 | 
			
		||||
 | 
			
		||||
    def form_valid(self, form):
 | 
			
		||||
        otp_code = form.cleaned_data.get('otp_code')
 | 
			
		||||
        otp_secret_key = self.request.session.get('otp_secret_key', '')
 | 
			
		||||
| 
						 | 
				
			
			@ -116,6 +160,7 @@ class UserOtpUpdateView(FormView):
 | 
			
		|||
 | 
			
		||||
        valid = user.check_mfa(otp_code)
 | 
			
		||||
        if valid:
 | 
			
		||||
            self.request.session['auth_opt_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
 | 
			
		||||
            return super().form_valid(form)
 | 
			
		||||
        else:
 | 
			
		||||
            error = _('MFA code invalid, or ntp sync server time')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,10 @@
 | 
			
		|||
# ~*~ coding: utf-8 ~*~
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.auth import authenticate
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
from django.urls import reverse_lazy, reverse
 | 
			
		||||
from django.urls import reverse_lazy
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
from django.views.generic.edit import UpdateView, FormView
 | 
			
		||||
from django.contrib.auth import logout as auth_logout
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +78,7 @@ class UserVerifyPasswordView(FormView):
 | 
			
		|||
            user.save()
 | 
			
		||||
        self.request.session['user_id'] = str(user.id)
 | 
			
		||||
        self.request.session['auth_password'] = 1
 | 
			
		||||
        self.request.session['auth_password_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
 | 
			
		||||
        return redirect(self.get_success_url())
 | 
			
		||||
 | 
			
		||||
    def get_success_url(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue