* [Update] 统一url地址

* [Update] 修改api

* [Update] 使用规范的签名

* [Update] 修改url

* [Update] 修改swagger

* [Update] 添加serializer class避免报错

* [Update] 修改token

* [Update] 支持api key

* [Update] 支持生成api key

* [Update] 修改api重定向

* [Update] 修改翻译

* [Update] 添加说明文档

* [Update] 修复浏览器关闭后session不失效的问题

* [Update] 修改一些内容

* [Update] 修改 jms脚本

* [Update] 修改重定向

* [Update] 修改搜索trim

* [Update] 修改搜索trim

* [Update] 添加sys log

* [Bugfix] 修改登陆错误

* [Update] 优化User操作private_token的接口 (#3091)

* [Update] 优化User操作private_token的接口

* [Update] 优化User操作private_token的接口 2

* [Bugfix] 解决授权了一个节点,当移动节点后,被移动的节点下的资产会放到未分组节点下的问题

* [Update] 升级jquery

* [Update] 默认使用page

* [Update] 修改使用Orgmodel view set

* [Update] 支持 nv的硬盘 https://github.com/jumpserver/jumpserver/issues/1804

* [UPdate] 解决命令执行宽度问题

* [Update] 优化节点

* [Update] 修改nodes过多时创建比较麻烦

* [Update] 修改导入

* [Update] 节点获取更新

* [Update] 修改nodes

* [Update] nodes显示full value

* [Update] 统一使用nodes select2 函数

* [Update] 修改磁盘大小小数

* [Update] 修改 Node service

* [Update] 优化授权节点

* [Update] 修改 node permission

* [Update] 修改asset permission

* [Stash]

* [Update] 修改node assets api

* [Update] 修改tree service,支持资产数量

* [Update] 修改暂时完成

* [Update] 修改一些bug
This commit is contained in:
老广
2019-08-21 20:27:21 +08:00
committed by GitHub
parent fe6f7bcfc1
commit 164f48e131
144 changed files with 2620 additions and 2331 deletions

View File

@@ -2,3 +2,6 @@
#
from .auth import *
from .token import *
from .mfa import *
from .access_key import *

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
#
from rest_framework.viewsets import ModelViewSet
from common.permissions import IsValidUser
from .. import serializers
class AccessKeyViewSet(ModelViewSet):
permission_classes = (IsValidUser,)
serializer_class = serializers.AccessKeySerializer
search_fields = ['^id', '^secret']
def get_queryset(self):
return self.request.user.access_keys.all()
def perform_create(self, serializer):
user = self.request.user
user.create_access_key()

View File

@@ -16,15 +16,17 @@ from rest_framework.views import APIView
from common.utils import get_logger, get_request_ip
from common.permissions import IsOrgAdminOrAppUser, IsValidUser
from orgs.mixins import RootOrgViewMixin
from orgs.mixins.api import RootOrgViewMixin
from users.serializers import UserSerializer
from users.models import User
from assets.models import Asset, SystemUser
from audits.models import UserLoginLog as LoginLog
from users.utils import (
check_user_valid, check_otp_code, increase_login_failed_count,
check_otp_code, increase_login_failed_count,
is_block_login, clean_failed_count
)
from .. import const
from ..utils import check_user_valid
from ..serializers import OtpVerifySerializer
from ..signals import post_auth_success, post_auth_failed
@@ -53,27 +55,15 @@ class UserAuthApi(RootOrgViewMixin, APIView):
user, msg = self.check_user_valid(request)
if not user:
username = request.data.get('username', '')
exist = User.objects.filter(username=username).first()
reason = LoginLog.REASON_PASSWORD if exist else LoginLog.REASON_NOT_EXIST
self.send_auth_signal(success=False, username=username, reason=reason)
self.send_auth_signal(success=False, username=username, reason=msg)
increase_login_failed_count(username, ip)
return Response({'msg': msg}, status=401)
if user.password_has_expired:
self.send_auth_signal(
success=False, username=username,
reason=LoginLog.REASON_PASSWORD_EXPIRED
)
msg = _("The user {} password has expired, please update.".format(
user.username))
logger.info(msg)
return Response({'msg': msg}, status=401)
if not user.otp_enabled:
self.send_auth_signal(success=True, user=user)
# 登陆成功,清除原来的缓存计数
clean_failed_count(username, ip)
token = user.create_bearer_token(request)
token, expired_at = user.create_bearer_token(request)
return Response(
{'token': token, 'user': self.serializer_class(user).data}
)
@@ -167,10 +157,10 @@ class UserOtpAuthApi(RootOrgViewMixin, APIView):
status=401
)
if not check_otp_code(user.otp_secret_key, otp_code):
self.send_auth_signal(success=False, username=user.username, reason=LoginLog.REASON_MFA)
self.send_auth_signal(success=False, username=user.username, reason=const.mfa_failed)
return Response({'msg': _('MFA certification failed')}, status=401)
self.send_auth_signal(success=True, user=user)
token = user.create_bearer_token(request)
token, expired_at = user.create_bearer_token(request)
data = {'token': token, 'user': self.serializer_class(user).data}
return Response(data)

View File

@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
#
from rest_framework.permissions import AllowAny
from rest_framework.generics import CreateAPIView
from .. import serializers
class MFAChallengeApi(CreateAPIView):
permission_classes = (AllowAny,)
serializer_class = serializers.MFAChallengeSerializer

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
#
import uuid
from django.core.cache import cache
from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from drf_yasg.utils import swagger_auto_schema
from common.utils import get_request_ip, get_logger
from users.utils import (
check_otp_code, increase_login_failed_count,
is_block_login, clean_failed_count
)
from ..utils import check_user_valid
from ..signals import post_auth_success, post_auth_failed
from .. import serializers
logger = get_logger(__name__)
__all__ = ['TokenCreateApi']
class AuthFailedError(Exception):
def __init__(self, msg, reason=None):
self.msg = msg
self.reason = reason
class MFARequiredError(Exception):
pass
class TokenCreateApi(CreateAPIView):
permission_classes = (AllowAny,)
serializer_class = serializers.BearerTokenSerializer
@staticmethod
def check_is_block(username, ip):
if is_block_login(username, ip):
msg = _("Log in frequently and try again later")
logger.warn(msg + ': ' + username + ':' + ip)
raise AuthFailedError(msg)
def check_user_valid(self):
request = self.request
username = request.data.get('username', '')
password = request.data.get('password', '')
public_key = request.data.get('public_key', '')
user, msg = check_user_valid(
username=username, password=password,
public_key=public_key
)
if not user:
raise AuthFailedError(msg)
return user
def create(self, request, *args, **kwargs):
username = self.request.data.get('username')
ip = self.request.data.get('remote_addr', None)
ip = ip or get_request_ip(self.request)
user = None
try:
self.check_is_block(username, ip)
user = self.check_user_valid()
if user.otp_enabled:
raise MFARequiredError()
self.send_auth_signal(success=True, user=user)
clean_failed_count(username, ip)
return super().create(request, *args, **kwargs)
except AuthFailedError as e:
increase_login_failed_count(username, ip)
self.send_auth_signal(success=False, user=user, username=username, reason=str(e))
return Response({'msg': str(e)}, status=401)
except MFARequiredError:
msg = _("MFA required")
seed = uuid.uuid4().hex
cache.set(seed, user.username, 300)
resp = {'msg': msg, "choices": ["otp"], "req": seed}
return Response(resp, status=300)
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
post_auth_success.send(
sender=self.__class__, user=user, request=self.request
)
else:
post_auth_failed.send(
sender=self.__class__, username=username,
request=self.request, reason=reason
)