diff --git a/apps/authentication/views/mfa.py b/apps/authentication/views/mfa.py index 9347ff97c..35fa58f94 100644 --- a/apps/authentication/views/mfa.py +++ b/apps/authentication/views/mfa.py @@ -48,7 +48,7 @@ class UserLoginOtpView(mixins.AuthMixin, FormView): { 'name': 'sms', 'label': _('SMS'), - 'enable': bool(user.phone) and settings.AUTH_SMS, + 'enable': bool(user.phone) and settings.SMS_ENABLED and settings.XPACK_ENABLED, 'selected': False, }, ] diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 3e5ce3b0a..74fd3b708 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -243,7 +243,7 @@ class Config(dict): 'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS 'LOGIN_REDIRECT_MSG_ENABLED': True, - 'AUTH_SMS': False, + 'SMS_ENABLED': False, 'SMS_BACKEND': '', 'SMS_TEST_PHONE': '', diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index e06ec9028..ac9fdb631 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -123,7 +123,7 @@ FEISHU_APP_ID = CONFIG.FEISHU_APP_ID FEISHU_APP_SECRET = CONFIG.FEISHU_APP_SECRET # SMS auth -AUTH_SMS = CONFIG.AUTH_SMS +SMS_ENABLED = CONFIG.SMS_ENABLED SMS_BACKEND = CONFIG.SMS_BACKEND SMS_TEST_PHONE = CONFIG.SMS_TEST_PHONE diff --git a/apps/notifications/backends/sms.py b/apps/notifications/backends/sms.py index a4deb02c7..77a720a04 100644 --- a/apps/notifications/backends/sms.py +++ b/apps/notifications/backends/sms.py @@ -6,7 +6,7 @@ from .base import BackendBase class SMS(BackendBase): account_field = 'phone' - is_enable_field_in_settings = 'AUTH_SMS' + is_enable_field_in_settings = 'SMS_ENABLED' def __init__(self): """ diff --git a/apps/notifications/migrations/0001_initial.py b/apps/notifications/migrations/0001_initial.py index ebe79f304..8b52fb84f 100644 --- a/apps/notifications/migrations/0001_initial.py +++ b/apps/notifications/migrations/0001_initial.py @@ -44,7 +44,7 @@ class Migration(migrations.Migration): ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('message_type', models.CharField(max_length=128)), ('receive_backends', models.JSONField(default=list)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_msg_subscriptions', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_msg_subscription', to=settings.AUTH_USER_MODEL)), ], options={ 'abstract': False, diff --git a/apps/notifications/migrations/0002_auto_20210823_1619.py b/apps/notifications/migrations/0002_auto_20210909_1946.py similarity index 72% rename from apps/notifications/migrations/0002_auto_20210823_1619.py rename to apps/notifications/migrations/0002_auto_20210909_1946.py index 26230e9d8..c7006130d 100644 --- a/apps/notifications/migrations/0002_auto_20210823_1619.py +++ b/apps/notifications/migrations/0002_auto_20210909_1946.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.12 on 2021-08-23 08:19 +# Generated by Django 3.1.12 on 2021-09-09 11:46 from django.conf import settings from django.db import migrations, models @@ -20,6 +20,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='usermsgsubscription', name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_msg_subscriptions', to=settings.AUTH_USER_MODEL, unique=True), + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_msg_subscription', to=settings.AUTH_USER_MODEL), ), ] diff --git a/apps/notifications/migrations/0003_init_user_msg_subscription.py b/apps/notifications/migrations/0003_init_user_msg_subscription.py index 2c684c86a..093bf8749 100644 --- a/apps/notifications/migrations/0003_init_user_msg_subscription.py +++ b/apps/notifications/migrations/0003_init_user_msg_subscription.py @@ -35,7 +35,7 @@ class Migration(migrations.Migration): dependencies = [ ('users', '0036_user_feishu_id'), - ('notifications', '0002_auto_20210823_1619'), + ('notifications', '0002_auto_20210909_1946'), ] operations = [ diff --git a/apps/notifications/models/notification.py b/apps/notifications/models/notification.py index 21a5d3f0b..d50168576 100644 --- a/apps/notifications/models/notification.py +++ b/apps/notifications/models/notification.py @@ -6,7 +6,7 @@ __all__ = ('SystemMsgSubscription', 'UserMsgSubscription') class UserMsgSubscription(JMSModel): - user = models.OneToOneField('users.User', related_name='user_msg_subscriptions', on_delete=models.CASCADE) + user = models.OneToOneField('users.User', related_name='user_msg_subscription', on_delete=models.CASCADE) receive_backends = models.JSONField(default=list) def __str__(self): diff --git a/apps/notifications/notifications.py b/apps/notifications/notifications.py index 31e4067fc..1141c104f 100644 --- a/apps/notifications/notifications.py +++ b/apps/notifications/notifications.py @@ -68,6 +68,9 @@ class Message(metaclass=MessageType): raise NotImplementedError def send_msg(self, users: Iterable, backends: Iterable = BACKEND): + backends = set(backends) + backends.add(BACKEND.SITE_MSG) # 站内信必须发 + for backend in backends: try: backend = BACKEND(backend) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index 977dc76ea..275a8436e 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -7,7 +7,7 @@ __all__ = ['AlibabaSMSSettingSerializer', 'TencentSMSSettingSerializer'] class BaseSMSSettingSerializer(serializers.Serializer): - AUTH_SMS = serializers.BooleanField(default=False, label=_('Enable SMS')) + SMS_ENABLED = serializers.BooleanField(default=False, label=_('Enable SMS')) SMS_TEST_PHONE = serializers.CharField(max_length=256, required=False, label=_('Test phone')) def to_representation(self, instance): diff --git a/apps/users/models/user.py b/apps/users/models/user.py index d8d981f13..9911bf91b 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -565,9 +565,17 @@ class MFAMixin: def mfa_enabled_but_not_set(self): if not self.mfa_enabled: return False, None - if self.mfa_is_otp() and not self.otp_secret_key and not self.phone: - return True, reverse('authentication:user-otp-enable-start') - return False, None + + if not self.mfa_is_otp(): + return False, None + + if self.mfa_is_otp() and self.otp_secret_key: + return False, None + + if self.phone and settings.SMS_ENABLED and settings.XPACK_ENABLED: + return False, None + + return True, reverse('authentication:user-otp-enable-start') class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): @@ -661,6 +669,10 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): group_ids = list(group_ids) return group_ids + @property + def receive_backends(self): + return self.user_msg_subscription.receive_backends + @property def is_wecom_bound(self): return bool(self.wecom_id) diff --git a/apps/users/serializers/profile.py b/apps/users/serializers/profile.py index 09ab50cc0..74e8e460b 100644 --- a/apps/users/serializers/profile.py +++ b/apps/users/serializers/profile.py @@ -101,16 +101,17 @@ class UserProfileSerializer(UserSerializer): ) mfa_level = serializers.ChoiceField(choices=MFA_LEVEL_CHOICES, label=_('MFA'), required=False) guide_url = serializers.SerializerMethodField() + receive_backends = serializers.ListField(child=serializers.CharField()) class Meta(UserSerializer.Meta): fields = UserSerializer.Meta.fields + [ 'public_key_comment', 'public_key_hash_md5', 'admin_or_audit_orgs', 'current_org_roles', 'guide_url', 'user_all_orgs', 'is_org_admin', - 'is_superuser' + 'is_superuser', 'receive_backends', ] read_only_fields = [ - 'date_joined', 'last_login', 'created_by', 'source' + 'date_joined', 'last_login', 'created_by', 'source', 'receive_backends', ] extra_kwargs = dict(UserSerializer.Meta.extra_kwargs) extra_kwargs.update({