mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-07-17 16:31:28 +00:00
perf: Third-party user login settings default organization
This commit is contained in:
parent
96399f8315
commit
bd3909ad27
1
apps/authentication/backends/radius/__init__.py
Normal file
1
apps/authentication/backends/radius/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .backends import *
|
@ -2,12 +2,12 @@
|
|||||||
#
|
#
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from radiusauth.backends import RADIUSBackend, RADIUSRealmBackend
|
from radiusauth.backends import RADIUSBackend, RADIUSRealmBackend
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from .base import JMSBaseAuthBackend
|
|
||||||
|
|
||||||
|
from authentication.backends.base import JMSBaseAuthBackend
|
||||||
|
from .signals import radius_create_user
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
@ -28,8 +28,8 @@ class CreateUserMixin:
|
|||||||
email = '{}@{}'.format(username, email_suffix)
|
email = '{}@{}'.format(username, email_suffix)
|
||||||
|
|
||||||
user = User(username=username, name=username, email=email)
|
user = User(username=username, name=username, email=email)
|
||||||
user.source = user.Source.radius.value
|
|
||||||
user.save()
|
user.save()
|
||||||
|
radius_create_user.send(sender=user.__class__, user=user)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def _perform_radius_auth(self, client, packet):
|
def _perform_radius_auth(self, client, packet):
|
3
apps/authentication/backends/radius/signals.py
Normal file
3
apps/authentication/backends/radius/signals.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.dispatch import Signal
|
||||||
|
|
||||||
|
radius_create_user = Signal()
|
@ -15,7 +15,7 @@ from common.utils import get_logger
|
|||||||
from common.utils.common import get_request_ip
|
from common.utils.common import get_request_ip
|
||||||
from common.utils.django import reverse, get_object_or_none
|
from common.utils.django import reverse, get_object_or_none
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from users.signal_handlers import check_only_allow_exist_user_auth
|
from users.signal_handlers import check_only_allow_exist_user_auth, bind_user_to_org_role
|
||||||
from .mixins import FlashMessageMixin
|
from .mixins import FlashMessageMixin
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
@ -64,6 +64,7 @@ class BaseLoginCallbackView(AuthMixin, FlashMessageMixin, IMClientMixin, View):
|
|||||||
setattr(user, f'{self.user_type}_id', user_id)
|
setattr(user, f'{self.user_type}_id', user_id)
|
||||||
if create:
|
if create:
|
||||||
setattr(user, 'source', self.user_type)
|
setattr(user, 'source', self.user_type)
|
||||||
|
bind_user_to_org_role(user)
|
||||||
user.save()
|
user.save()
|
||||||
except IntegrityError as err:
|
except IntegrityError as err:
|
||||||
logger.error(f'{self.msg_client_err}: create user error: {err}')
|
logger.error(f'{self.msg_client_err}: create user error: {err}')
|
||||||
|
@ -28,6 +28,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
PROJECT_DIR = os.path.dirname(BASE_DIR)
|
PROJECT_DIR = os.path.dirname(BASE_DIR)
|
||||||
XPACK_DIR = os.path.join(BASE_DIR, 'xpack')
|
XPACK_DIR = os.path.join(BASE_DIR, 'xpack')
|
||||||
HAS_XPACK = os.path.isdir(XPACK_DIR)
|
HAS_XPACK = os.path.isdir(XPACK_DIR)
|
||||||
|
DEFAULT_ID = '00000000-0000-0000-0000-000000000002'
|
||||||
|
|
||||||
logger = logging.getLogger('jumpserver.conf')
|
logger = logging.getLogger('jumpserver.conf')
|
||||||
|
|
||||||
@ -282,7 +283,7 @@ class Config(dict):
|
|||||||
'AUTH_LDAP_SYNC_IS_PERIODIC': False,
|
'AUTH_LDAP_SYNC_IS_PERIODIC': False,
|
||||||
'AUTH_LDAP_SYNC_INTERVAL': None,
|
'AUTH_LDAP_SYNC_INTERVAL': None,
|
||||||
'AUTH_LDAP_SYNC_CRONTAB': None,
|
'AUTH_LDAP_SYNC_CRONTAB': None,
|
||||||
'AUTH_LDAP_SYNC_ORG_IDS': ['00000000-0000-0000-0000-000000000002'],
|
'AUTH_LDAP_SYNC_ORG_IDS': [DEFAULT_ID],
|
||||||
'AUTH_LDAP_SYNC_RECEIVERS': [],
|
'AUTH_LDAP_SYNC_RECEIVERS': [],
|
||||||
'AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS': False,
|
'AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS': False,
|
||||||
'AUTH_LDAP_OPTIONS_OPT_REFERRALS': -1,
|
'AUTH_LDAP_OPTIONS_OPT_REFERRALS': -1,
|
||||||
@ -323,6 +324,7 @@ class Config(dict):
|
|||||||
'AUTH_OPENID_KEYCLOAK': True,
|
'AUTH_OPENID_KEYCLOAK': True,
|
||||||
'AUTH_OPENID_SERVER_URL': 'https://keycloak.example.com',
|
'AUTH_OPENID_SERVER_URL': 'https://keycloak.example.com',
|
||||||
'AUTH_OPENID_REALM_NAME': None,
|
'AUTH_OPENID_REALM_NAME': None,
|
||||||
|
'OPENID_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# Raidus 认证
|
# Raidus 认证
|
||||||
'AUTH_RADIUS': False,
|
'AUTH_RADIUS': False,
|
||||||
@ -332,6 +334,7 @@ class Config(dict):
|
|||||||
'RADIUS_ATTRIBUTES': {},
|
'RADIUS_ATTRIBUTES': {},
|
||||||
'RADIUS_ENCRYPT_PASSWORD': True,
|
'RADIUS_ENCRYPT_PASSWORD': True,
|
||||||
'OTP_IN_RADIUS': False,
|
'OTP_IN_RADIUS': False,
|
||||||
|
'RADIUS_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# Cas 认证
|
# Cas 认证
|
||||||
'AUTH_CAS': False,
|
'AUTH_CAS': False,
|
||||||
@ -343,6 +346,7 @@ class Config(dict):
|
|||||||
'CAS_APPLY_ATTRIBUTES_TO_USER': False,
|
'CAS_APPLY_ATTRIBUTES_TO_USER': False,
|
||||||
'CAS_RENAME_ATTRIBUTES': {'cas:user': 'username'},
|
'CAS_RENAME_ATTRIBUTES': {'cas:user': 'username'},
|
||||||
'CAS_CREATE_USER': True,
|
'CAS_CREATE_USER': True,
|
||||||
|
'CAS_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
'AUTH_SSO': False,
|
'AUTH_SSO': False,
|
||||||
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
|
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
|
||||||
@ -370,6 +374,7 @@ class Config(dict):
|
|||||||
'SAML2_SP_CERT_CONTENT': '',
|
'SAML2_SP_CERT_CONTENT': '',
|
||||||
'AUTH_SAML2_PROVIDER_AUTHORIZATION_ENDPOINT': '/',
|
'AUTH_SAML2_PROVIDER_AUTHORIZATION_ENDPOINT': '/',
|
||||||
'AUTH_SAML2_AUTHENTICATION_FAILURE_REDIRECT_URI': '/',
|
'AUTH_SAML2_AUTHENTICATION_FAILURE_REDIRECT_URI': '/',
|
||||||
|
'SAML2_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# OAuth2 认证
|
# OAuth2 认证
|
||||||
'AUTH_OAUTH2': False,
|
'AUTH_OAUTH2': False,
|
||||||
@ -388,6 +393,8 @@ class Config(dict):
|
|||||||
'AUTH_OAUTH2_USER_ATTR_MAP': {
|
'AUTH_OAUTH2_USER_ATTR_MAP': {
|
||||||
'name': 'name', 'username': 'username', 'email': 'email'
|
'name': 'name', 'username': 'username', 'email': 'email'
|
||||||
},
|
},
|
||||||
|
'OAUTH2_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
'AUTH_PASSKEY': False,
|
'AUTH_PASSKEY': False,
|
||||||
'FIDO_SERVER_ID': '',
|
'FIDO_SERVER_ID': '',
|
||||||
'FIDO_SERVER_NAME': 'JumpServer',
|
'FIDO_SERVER_NAME': 'JumpServer',
|
||||||
@ -402,6 +409,7 @@ class Config(dict):
|
|||||||
'username': 'userid',
|
'username': 'userid',
|
||||||
'email': 'email'
|
'email': 'email'
|
||||||
},
|
},
|
||||||
|
'WECOM_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# 钉钉
|
# 钉钉
|
||||||
'AUTH_DINGTALK': False,
|
'AUTH_DINGTALK': False,
|
||||||
@ -413,6 +421,7 @@ class Config(dict):
|
|||||||
'username': 'user_id',
|
'username': 'user_id',
|
||||||
'email': 'email'
|
'email': 'email'
|
||||||
},
|
},
|
||||||
|
'DINGTALK_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# 飞书
|
# 飞书
|
||||||
'AUTH_FEISHU': False,
|
'AUTH_FEISHU': False,
|
||||||
@ -423,6 +432,7 @@ class Config(dict):
|
|||||||
'username': 'user_id',
|
'username': 'user_id',
|
||||||
'email': 'enterprise_email'
|
'email': 'enterprise_email'
|
||||||
},
|
},
|
||||||
|
'FEISHU_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# Lark
|
# Lark
|
||||||
'AUTH_LARK': False,
|
'AUTH_LARK': False,
|
||||||
@ -433,6 +443,7 @@ class Config(dict):
|
|||||||
'username': 'user_id',
|
'username': 'user_id',
|
||||||
'email': 'enterprise_email'
|
'email': 'enterprise_email'
|
||||||
},
|
},
|
||||||
|
'LARK_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
# Slack
|
# Slack
|
||||||
'AUTH_SLACK': False,
|
'AUTH_SLACK': False,
|
||||||
@ -444,6 +455,7 @@ class Config(dict):
|
|||||||
'username': 'name',
|
'username': 'name',
|
||||||
'email': 'profile.email'
|
'email': 'profile.email'
|
||||||
},
|
},
|
||||||
|
'SLACK_ORG_IDS': [DEFAULT_ID],
|
||||||
|
|
||||||
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS / SAML2
|
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS / SAML2
|
||||||
'LOGIN_REDIRECT_MSG_ENABLED': True,
|
'LOGIN_REDIRECT_MSG_ENABLED': True,
|
||||||
|
@ -3,6 +3,7 @@ from rest_framework import serializers
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AuthSettingSerializer',
|
'AuthSettingSerializer',
|
||||||
|
'OrgListField'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -42,3 +43,17 @@ class AuthSettingSerializer(serializers.Serializer):
|
|||||||
"authentication when the administrator enables third-party redirect authentication"
|
"authentication when the administrator enables third-party redirect authentication"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class OrgListField(serializers.ListField):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
defaults = {
|
||||||
|
'required': False,
|
||||||
|
'label': _('Organization'),
|
||||||
|
'help_text': _(
|
||||||
|
'When you create a user, you associate the user to the organization of your choice. '
|
||||||
|
'Users always belong to the Default organization.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
super().__init__(**defaults)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'CASSettingSerializer',
|
'CASSettingSerializer',
|
||||||
]
|
]
|
||||||
@ -42,3 +44,4 @@ class CASSettingSerializer(serializers.Serializer):
|
|||||||
'automatically create the user'
|
'automatically create the user'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
CAS_ORG_IDS = OrgListField()
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = ['DingTalkSettingSerializer']
|
__all__ = ['DingTalkSettingSerializer']
|
||||||
|
|
||||||
@ -20,3 +21,4 @@ class DingTalkSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the DingTalk service user attribute name'
|
'`value` is the DingTalk service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
DINGTALK_ORG_IDS = OrgListField()
|
||||||
|
@ -5,6 +5,8 @@ from common.serializers.fields import EncryptedField
|
|||||||
|
|
||||||
__all__ = ['FeiShuSettingSerializer']
|
__all__ = ['FeiShuSettingSerializer']
|
||||||
|
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
|
|
||||||
class FeiShuSettingSerializer(serializers.Serializer):
|
class FeiShuSettingSerializer(serializers.Serializer):
|
||||||
PREFIX_TITLE = _('FeiShu')
|
PREFIX_TITLE = _('FeiShu')
|
||||||
@ -19,3 +21,4 @@ class FeiShuSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the FeiShu service user attribute name'
|
'`value` is the FeiShu service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
FEISHU_ORG_IDS = OrgListField()
|
||||||
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = ['LarkSettingSerializer']
|
__all__ = ['LarkSettingSerializer']
|
||||||
|
|
||||||
@ -19,3 +20,4 @@ class LarkSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the Lark service user attribute name'
|
'`value` is the Lark service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
LARK_ORG_IDS = OrgListField()
|
||||||
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer',
|
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer',
|
||||||
@ -67,9 +68,6 @@ class LDAPSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the LDAP service user attribute name'
|
'`value` is the LDAP service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AUTH_LDAP_SYNC_ORG_IDS = serializers.ListField(
|
|
||||||
required=False, label=_('Organization'), max_length=36
|
|
||||||
)
|
|
||||||
AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField(
|
AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField(
|
||||||
required=False, label=_('Periodic run')
|
required=False, label=_('Periodic run')
|
||||||
)
|
)
|
||||||
@ -102,6 +100,7 @@ class LDAPSettingSerializer(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
AUTH_LDAP = serializers.BooleanField(required=False, label=_('LDAP'))
|
AUTH_LDAP = serializers.BooleanField(required=False, label=_('LDAP'))
|
||||||
|
AUTH_LDAP_SYNC_ORG_IDS = OrgListField()
|
||||||
|
|
||||||
def post_save(self):
|
def post_save(self):
|
||||||
keys = ['AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_CRONTAB']
|
keys = ['AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_CRONTAB']
|
||||||
|
@ -3,6 +3,7 @@ from rest_framework import serializers
|
|||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
from common.utils import static_or_direct
|
from common.utils import static_or_direct
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'OAuth2SettingSerializer',
|
'OAuth2SettingSerializer',
|
||||||
@ -65,3 +66,4 @@ class OAuth2SettingSerializer(serializers.Serializer):
|
|||||||
AUTH_OAUTH2_ALWAYS_UPDATE_USER = serializers.BooleanField(
|
AUTH_OAUTH2_ALWAYS_UPDATE_USER = serializers.BooleanField(
|
||||||
default=True, label=_('Always update user')
|
default=True, label=_('Always update user')
|
||||||
)
|
)
|
||||||
|
OAUTH2_ORG_IDS = OrgListField()
|
||||||
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'OIDCSettingSerializer', 'KeycloakSettingSerializer',
|
'OIDCSettingSerializer', 'KeycloakSettingSerializer',
|
||||||
@ -111,3 +112,4 @@ class OIDCSettingSerializer(KeycloakSettingSerializer):
|
|||||||
AUTH_OPENID_ALWAYS_UPDATE_USER = serializers.BooleanField(
|
AUTH_OPENID_ALWAYS_UPDATE_USER = serializers.BooleanField(
|
||||||
required=False, label=_('Always update user')
|
required=False, label=_('Always update user')
|
||||||
)
|
)
|
||||||
|
OPENID_ORG_IDS = OrgListField()
|
||||||
|
@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = ['RadiusSettingSerializer']
|
__all__ = ['RadiusSettingSerializer']
|
||||||
|
|
||||||
@ -22,3 +23,4 @@ class RadiusSettingSerializer(serializers.Serializer):
|
|||||||
required=False, label=_('OTP in RADIUS'),
|
required=False, label=_('OTP in RADIUS'),
|
||||||
help_text=_('* Using OTP in RADIUS means users can employ RADIUS as a method for MFA')
|
help_text=_('* Using OTP in RADIUS means users can employ RADIUS as a method for MFA')
|
||||||
)
|
)
|
||||||
|
RADIUS_ORG_IDS = OrgListField()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'SAML2SettingSerializer',
|
'SAML2SettingSerializer',
|
||||||
]
|
]
|
||||||
@ -41,3 +43,4 @@ class SAML2SettingSerializer(serializers.Serializer):
|
|||||||
help_text=_('When the user signs out, they also be logged out from the SAML2 server')
|
help_text=_('When the user signs out, they also be logged out from the SAML2 server')
|
||||||
)
|
)
|
||||||
AUTH_SAML2_ALWAYS_UPDATE_USER = serializers.BooleanField(required=False, label=_('Always update user'))
|
AUTH_SAML2_ALWAYS_UPDATE_USER = serializers.BooleanField(required=False, label=_('Always update user'))
|
||||||
|
SAML2_ORG_IDS = OrgListField()
|
||||||
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = ['SlackSettingSerializer']
|
__all__ = ['SlackSettingSerializer']
|
||||||
|
|
||||||
@ -20,3 +21,4 @@ class SlackSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the Slack service user attribute name'
|
'`value` is the Slack service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
SLACK_ORG_IDS = OrgListField()
|
||||||
|
@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import EncryptedField
|
from common.serializers.fields import EncryptedField
|
||||||
|
from .base import OrgListField
|
||||||
|
|
||||||
__all__ = ['WeComSettingSerializer']
|
__all__ = ['WeComSettingSerializer']
|
||||||
|
|
||||||
@ -20,3 +21,4 @@ class WeComSettingSerializer(serializers.Serializer):
|
|||||||
'`value` is the WeCom service user attribute name'
|
'`value` is the WeCom service user attribute name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
WECOM_ORG_IDS = OrgListField()
|
||||||
|
@ -183,6 +183,7 @@ class RoleMixin:
|
|||||||
is_authenticated: bool
|
is_authenticated: bool
|
||||||
is_valid: bool
|
is_valid: bool
|
||||||
id: str
|
id: str
|
||||||
|
source: str
|
||||||
_org_roles = None
|
_org_roles = None
|
||||||
_system_roles = None
|
_system_roles = None
|
||||||
PERM_CACHE_KEY = "USER_PERMS_ROLES_{}_{}"
|
PERM_CACHE_KEY = "USER_PERMS_ROLES_{}_{}"
|
||||||
|
@ -12,6 +12,7 @@ from django_cas_ng.signals import cas_user_authenticated
|
|||||||
from audits.models import UserSession
|
from audits.models import UserSession
|
||||||
from authentication.backends.oauth2.signals import oauth2_create_or_update_user
|
from authentication.backends.oauth2.signals import oauth2_create_or_update_user
|
||||||
from authentication.backends.oidc.signals import openid_create_or_update_user
|
from authentication.backends.oidc.signals import openid_create_or_update_user
|
||||||
|
from authentication.backends.radius.signals import radius_create_user
|
||||||
from authentication.backends.saml2.signals import saml2_create_or_update_user
|
from authentication.backends.saml2.signals import saml2_create_or_update_user
|
||||||
from common.const.crontab import CRONTAB_AT_AM_TWO
|
from common.const.crontab import CRONTAB_AT_AM_TWO
|
||||||
from common.decorators import on_transaction_commit
|
from common.decorators import on_transaction_commit
|
||||||
@ -20,6 +21,9 @@ from common.signals import django_ready
|
|||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from jumpserver.utils import get_current_request
|
from jumpserver.utils import get_current_request
|
||||||
from ops.celery.decorator import register_as_period_task
|
from ops.celery.decorator import register_as_period_task
|
||||||
|
from rbac.builtin import BuiltinRole
|
||||||
|
from rbac.const import Scope
|
||||||
|
from rbac.models import RoleBinding
|
||||||
from settings.signals import setting_changed
|
from settings.signals import setting_changed
|
||||||
from .models import User, UserPasswordHistory
|
from .models import User, UserPasswordHistory
|
||||||
from .signals import post_user_create
|
from .signals import post_user_create
|
||||||
@ -40,12 +44,13 @@ def check_only_allow_exist_user_auth(created):
|
|||||||
|
|
||||||
|
|
||||||
def user_authenticated_handle(user, created, source, attrs=None, **kwargs):
|
def user_authenticated_handle(user, created, source, attrs=None, **kwargs):
|
||||||
|
if not check_only_allow_exist_user_auth(created):
|
||||||
|
return
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
user.source = source
|
user.source = source
|
||||||
user.save()
|
user.save()
|
||||||
|
bind_user_to_org_role(user)
|
||||||
if not check_only_allow_exist_user_auth(created):
|
|
||||||
return
|
|
||||||
|
|
||||||
if not attrs:
|
if not attrs:
|
||||||
return
|
return
|
||||||
@ -133,17 +138,18 @@ def on_oauth2_create_or_update_user(sender, user, created, attrs, **kwargs):
|
|||||||
user_authenticated_handle(user, created, source, attrs, **kwargs)
|
user_authenticated_handle(user, created, source, attrs, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@receiver(populate_user)
|
@receiver(radius_create_user)
|
||||||
def on_ldap_create_user(sender, user, ldap_user, **kwargs):
|
def radius_create_user(sender, user, **kwargs):
|
||||||
if user and user.username not in ['admin']:
|
user.source = user.Source.radius.value
|
||||||
exists = User.objects.filter(username=user.username).exists()
|
|
||||||
if not exists:
|
|
||||||
user.source = user.Source.ldap.value
|
|
||||||
user.save()
|
user.save()
|
||||||
|
bind_user_to_org_role(user)
|
||||||
|
|
||||||
|
|
||||||
@receiver(openid_create_or_update_user)
|
@receiver(openid_create_or_update_user)
|
||||||
def on_openid_create_or_update_user(sender, request, user, created, name, username, email, **kwargs):
|
def on_openid_create_or_update_user(sender, request, user, created, name, username, email, **kwargs):
|
||||||
|
if not check_only_allow_exist_user_auth(created):
|
||||||
|
return
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Receive OpenID user created signal: {}, "
|
"Receive OpenID user created signal: {}, "
|
||||||
@ -151,9 +157,7 @@ def on_openid_create_or_update_user(sender, request, user, created, name, userna
|
|||||||
)
|
)
|
||||||
user.source = User.Source.openid.value
|
user.source = User.Source.openid.value
|
||||||
user.save()
|
user.save()
|
||||||
|
bind_user_to_org_role(user)
|
||||||
if not check_only_allow_exist_user_auth(created):
|
|
||||||
return
|
|
||||||
|
|
||||||
if not created and settings.AUTH_OPENID_ALWAYS_UPDATE_USER:
|
if not created and settings.AUTH_OPENID_ALWAYS_UPDATE_USER:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@ -167,6 +171,15 @@ def on_openid_create_or_update_user(sender, request, user, created, name, userna
|
|||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(populate_user)
|
||||||
|
def on_ldap_create_user(sender, user, ldap_user, **kwargs):
|
||||||
|
if user and user.username not in ['admin']:
|
||||||
|
exists = User.objects.filter(username=user.username).exists()
|
||||||
|
if not exists:
|
||||||
|
user.source = user.Source.ldap.value
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
@shared_task(verbose_name=_('Clean up expired user sessions'))
|
@shared_task(verbose_name=_('Clean up expired user sessions'))
|
||||||
@register_as_period_task(crontab=CRONTAB_AT_AM_TWO)
|
@register_as_period_task(crontab=CRONTAB_AT_AM_TWO)
|
||||||
def clean_expired_user_session_period():
|
def clean_expired_user_session_period():
|
||||||
@ -190,3 +203,25 @@ def on_auth_setting_changed_clear_source_choice(sender, name='', **kwargs):
|
|||||||
@receiver(django_ready)
|
@receiver(django_ready)
|
||||||
def on_django_ready_refresh_source(sender, **kwargs):
|
def on_django_ready_refresh_source(sender, **kwargs):
|
||||||
User._source_choices = []
|
User._source_choices = []
|
||||||
|
|
||||||
|
|
||||||
|
def bind_user_to_org_role(user):
|
||||||
|
source = user.source.upper()
|
||||||
|
org_ids = getattr(settings, f"{source}_ORG_IDS", None)
|
||||||
|
|
||||||
|
if not org_ids:
|
||||||
|
logger.error(f"User {user} has no {source} orgs")
|
||||||
|
return
|
||||||
|
|
||||||
|
org_role_ids = [BuiltinRole.org_user.id]
|
||||||
|
|
||||||
|
bindings = [
|
||||||
|
RoleBinding(
|
||||||
|
user=user, org_id=org_id, scope=Scope.org,
|
||||||
|
role_id=role_id,
|
||||||
|
)
|
||||||
|
for role_id in org_role_ids
|
||||||
|
for org_id in org_ids
|
||||||
|
]
|
||||||
|
|
||||||
|
RoleBinding.objects.bulk_create(bindings, ignore_conflicts=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user