diff --git a/apps/common/message/backends/sms/__init__.py b/apps/common/message/backends/sms/__init__.py index 760b55407..3eaf6fecf 100644 --- a/apps/common/message/backends/sms/__init__.py +++ b/apps/common/message/backends/sms/__init__.py @@ -11,34 +11,6 @@ from common.exceptions import JMSException logger = get_logger(__file__) -class SMS_MESSAGE(TextChoices): - """ - 定义短信的各种消息类型,会存到类似 `ALIBABA_SMS_SIGN_AND_TEMPLATES` settings 里 - - { - 'verification_code': {'sign_name': 'Jumpserver', 'template_code': 'SMS_222870834'}, - ... - } - """ - - """ - 验证码签名和模板。模板例子: - `您的验证码:${code},您正进行身份验证,打死不告诉别人!` - 其中必须包含 `code` 变量 - """ - VERIFICATION_CODE = 'verification_code' - - def get_sign_and_tmpl(self, config: dict): - try: - data = config[self] - return data['sign_name'], data['template_code'] - except KeyError as e: - raise JMSException( - code=f'{settings.SMS_BACKEND}_sign_and_tmpl_bad', - detail=_('Invalid SMS sign and template: {}').format(e) - ) - - class BACKENDS(TextChoices): ALIBABA = 'alibaba', _('Alibaba cloud') TENCENT = 'tencent', _('Tencent cloud') @@ -49,11 +21,7 @@ class BaseSMSClient: 短信终端的基类 """ - SIGN_AND_TMPL_SETTING_FIELD: str - - @property - def sign_and_tmpl(self): - return getattr(settings, self.SIGN_AND_TMPL_SETTING_FIELD, {}) + SIGN_AND_TMPL_SETTING_FIELD_PREFIX: str @classmethod def new_from_settings(cls): @@ -86,5 +54,12 @@ class SMS: ) def send_verify_code(self, phone_number, code): - sign_name, template_code = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(self.client.sign_and_tmpl) + sign_name = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_SIGN_NAME') + template_code = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_TEMPLATE_CODE') + + if not (sign_name and template_code): + raise JMSException( + code='verify_code_sign_tmpl_invalid', + detail=_('SMS verification code signature or template invalid') + ) return self.send_sms([phone_number], sign_name, template_code, OrderedDict(code=code)) diff --git a/apps/common/message/backends/sms/alibaba.py b/apps/common/message/backends/sms/alibaba.py index b664f4401..2c5532c4f 100644 --- a/apps/common/message/backends/sms/alibaba.py +++ b/apps/common/message/backends/sms/alibaba.py @@ -15,7 +15,7 @@ logger = get_logger(__file__) class AlibabaSMS(BaseSMSClient): - SIGN_AND_TMPL_SETTING_FIELD = 'ALIBABA_SMS_SIGN_AND_TEMPLATES' + SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'ALIBABA' @classmethod def new_from_settings(cls): diff --git a/apps/common/message/backends/sms/tencent.py b/apps/common/message/backends/sms/tencent.py index 6f796bb15..427e8b7dd 100644 --- a/apps/common/message/backends/sms/tencent.py +++ b/apps/common/message/backends/sms/tencent.py @@ -20,7 +20,7 @@ class TencentSMS(BaseSMSClient): """ https://cloud.tencent.com/document/product/382/43196#.E5.8F.91.E9.80.81.E7.9F.AD.E4.BF.A1 """ - SIGN_AND_TMPL_SETTING_FIELD = 'TENCENT_SMS_SIGN_AND_TEMPLATES' + SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'TENCENT' @classmethod def new_from_settings(cls): diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 74fd3b708..a2e96966f 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -249,12 +249,14 @@ class Config(dict): 'ALIBABA_ACCESS_KEY_ID': '', 'ALIBABA_ACCESS_KEY_SECRET': '', - 'ALIBABA_SMS_SIGN_AND_TEMPLATES': {}, + 'ALIBABA_VERIFY_SIGN_NAME': '', + 'ALIBABA_VERIFY_TEMPLATE_CODE': '', 'TENCENT_SECRET_ID': '', 'TENCENT_SECRET_KEY': '', 'TENCENT_SDKAPPID': '', - 'TENCENT_SMS_SIGN_AND_TEMPLATES': {}, + 'TENCENT_VERIFY_SIGN_NAME': '', + 'TENCENT_VERIFY_TEMPLATE_CODE': '', 'OTP_VALID_WINDOW': 2, 'OTP_ISSUER_NAME': 'JumpServer', diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index ac9fdb631..048c76a39 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -122,21 +122,7 @@ AUTH_FEISHU = CONFIG.AUTH_FEISHU FEISHU_APP_ID = CONFIG.FEISHU_APP_ID FEISHU_APP_SECRET = CONFIG.FEISHU_APP_SECRET -# SMS auth -SMS_ENABLED = CONFIG.SMS_ENABLED -SMS_BACKEND = CONFIG.SMS_BACKEND -SMS_TEST_PHONE = CONFIG.SMS_TEST_PHONE -# Alibaba -ALIBABA_ACCESS_KEY_ID = CONFIG.ALIBABA_ACCESS_KEY_ID -ALIBABA_ACCESS_KEY_SECRET = CONFIG.ALIBABA_ACCESS_KEY_SECRET -ALIBABA_SMS_SIGN_AND_TEMPLATES = CONFIG.ALIBABA_SMS_SIGN_AND_TEMPLATES - -# TENCENT -TENCENT_SECRET_ID = CONFIG.TENCENT_SECRET_ID -TENCENT_SECRET_KEY = CONFIG.TENCENT_SECRET_KEY -TENCENT_SDKAPPID = CONFIG.TENCENT_SDKAPPID -TENCENT_SMS_SIGN_AND_TEMPLATES = CONFIG.TENCENT_SMS_SIGN_AND_TEMPLATES # Other setting TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index 0ef447621..91973d1b2 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -132,3 +132,20 @@ LOGIN_REDIRECT_MSG_ENABLED = CONFIG.LOGIN_REDIRECT_MSG_ENABLED CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = CONFIG.CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS XRDP_ENABLED = CONFIG.XRDP_ENABLED + + +# SMS enabled +SMS_ENABLED = CONFIG.SMS_ENABLED +SMS_BACKEND = CONFIG.SMS_BACKEND +SMS_TEST_PHONE = CONFIG.SMS_TEST_PHONE + +# Alibaba +ALIBABA_ACCESS_KEY_ID = CONFIG.ALIBABA_ACCESS_KEY_ID +ALIBABA_ACCESS_KEY_SECRET = CONFIG.ALIBABA_ACCESS_KEY_SECRET +ALIBABA_SMS_SIGN_AND_TEMPLATES = CONFIG.ALIBABA_SMS_SIGN_AND_TEMPLATES + +# TENCENT +TENCENT_SECRET_ID = CONFIG.TENCENT_SECRET_ID +TENCENT_SECRET_KEY = CONFIG.TENCENT_SECRET_KEY +TENCENT_SDKAPPID = CONFIG.TENCENT_SDKAPPID +TENCENT_SMS_SIGN_AND_TEMPLATES = CONFIG.TENCENT_SMS_SIGN_AND_TEMPLATES diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index f5ecd7eb6..ac63b99c8 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index ebfe5b919..4dd34c8d4 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -2789,7 +2789,7 @@ msgstr "短信服务商" #: settings/serializers/auth/sms.py:15 settings/serializers/email.py:69 msgid "Signature" -msgstr "署名" +msgstr "签名" #: settings/serializers/auth/sms.py:16 msgid "Template" diff --git a/apps/settings/api/alibaba_sms.py b/apps/settings/api/alibaba_sms.py index c7f42f110..32460778e 100644 --- a/apps/settings/api/alibaba_sms.py +++ b/apps/settings/api/alibaba_sms.py @@ -4,7 +4,6 @@ from rest_framework.exceptions import APIException from rest_framework import status from django.utils.translation import gettext_lazy as _ -from common.message.backends.sms import SMS_MESSAGE from common.message.backends.sms.alibaba import AlibabaSMS from settings.models import Setting from common.permissions import IsSuperUser @@ -23,7 +22,8 @@ class AlibabaSMSTestingAPI(GenericAPIView): alibaba_access_key_id = serializer.validated_data['ALIBABA_ACCESS_KEY_ID'] alibaba_access_key_secret = serializer.validated_data.get('ALIBABA_ACCESS_KEY_SECRET') - alibaba_sms_sign_and_tmpl = serializer.validated_data['ALIBABA_SMS_SIGN_AND_TEMPLATES'] + alibaba_verify_sign_name = serializer.validated_data['ALIBABA_VERIFY_SIGN_NAME'] + alibaba_verify_template_code = serializer.validated_data['ALIBABA_VERIFY_TEMPLATE_CODE'] test_phone = serializer.validated_data.get('SMS_TEST_PHONE') if not test_phone: @@ -41,12 +41,11 @@ class AlibabaSMSTestingAPI(GenericAPIView): access_key_id=alibaba_access_key_id, access_key_secret=alibaba_access_key_secret ) - sign, tmpl = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(alibaba_sms_sign_and_tmpl) client.send_sms( phone_numbers=[test_phone], - sign_name=sign, - template_code=tmpl, + sign_name=alibaba_verify_sign_name, + template_code=alibaba_verify_template_code, template_param={'code': 'test'} ) return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')}) diff --git a/apps/settings/api/tencent_sms.py b/apps/settings/api/tencent_sms.py index 27ad07327..5395a1305 100644 --- a/apps/settings/api/tencent_sms.py +++ b/apps/settings/api/tencent_sms.py @@ -6,7 +6,6 @@ from rest_framework.exceptions import APIException from rest_framework import status from django.utils.translation import gettext_lazy as _ -from common.message.backends.sms import SMS_MESSAGE from common.message.backends.sms.tencent import TencentSMS from settings.models import Setting from common.permissions import IsSuperUser @@ -25,7 +24,8 @@ class TencentSMSTestingAPI(GenericAPIView): tencent_secret_id = serializer.validated_data['TENCENT_SECRET_ID'] tencent_secret_key = serializer.validated_data.get('TENCENT_SECRET_KEY') - tencent_sms_sign_and_tmpl = serializer.validated_data['TENCENT_SMS_SIGN_AND_TEMPLATES'] + tencent_verify_sign_name = serializer.validated_data['TENCENT_VERIFY_SIGN_NAME'] + tencent_verify_template_code = serializer.validated_data['TENCENT_VERIFY_TEMPLATE_CODE'] tencent_sdkappid = serializer.validated_data.get('TENCENT_SDKAPPID') test_phone = serializer.validated_data.get('SMS_TEST_PHONE') @@ -46,12 +46,11 @@ class TencentSMSTestingAPI(GenericAPIView): secret_key=tencent_secret_key, sdkappid=tencent_sdkappid ) - sign, tmpl = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(tencent_sms_sign_and_tmpl) client.send_sms( phone_numbers=[test_phone], - sign_name=sign, - template_code=tmpl, + sign_name=tencent_verify_sign_name, + template_code=tencent_verify_template_code, template_param=OrderedDict(code='test') ) return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')}) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index ad63a9907..8320b11eb 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -8,12 +8,14 @@ __all__ = ['SMSSettingSerializer', 'AlibabaSMSSettingSerializer', 'TencentSMSSet class SMSSettingSerializer(serializers.Serializer): SMS_ENABLED = serializers.BooleanField(default=False, label=_('Enable SMS')) - SMS_BACKEND = serializers.ChoiceField(choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider')) + SMS_BACKEND = serializers.ChoiceField( + choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider') + ) -class SignAndTmplPairSerializer(serializers.Serializer): - sign_name = serializers.CharField(max_length=256, required=True, label=_('Signature')) - template_code = serializers.CharField(max_length=256, required=True, label=_('Template')) +class SignTmplPairSerializer(serializers.Serializer): + SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) + TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code')) class BaseSMSSettingSerializer(serializers.Serializer): @@ -25,23 +27,18 @@ class BaseSMSSettingSerializer(serializers.Serializer): return data -class SignAndTmplSerializer(serializers.Serializer): - verification_code = SignAndTmplPairSerializer(default={'sign_name': '', 'template_code': ''}) - - class AlibabaSMSSettingSerializer(BaseSMSSettingSerializer): ALIBABA_ACCESS_KEY_ID = serializers.CharField(max_length=256, required=True, label='AccessKeyId') ALIBABA_ACCESS_KEY_SECRET = serializers.CharField( - max_length=256, required=False, label='AccessKeySecret', write_only=True) - ALIBABA_SMS_SIGN_AND_TEMPLATES = SignAndTmplSerializer( - label=_('Signatures and Templates'), required=True + max_length=256, required=False, label='AccessKeySecret', write_only=True ) + ALIBABA_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) + ALIBABA_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code')) class TencentSMSSettingSerializer(BaseSMSSettingSerializer): TENCENT_SECRET_ID = serializers.CharField(max_length=256, required=True, label='Secret id') TENCENT_SECRET_KEY = serializers.CharField(max_length=256, required=False, label='Secret key', write_only=True) TENCENT_SDKAPPID = serializers.CharField(max_length=256, required=True, label='SDK app id') - TENCENT_SMS_SIGN_AND_TEMPLATES = SignAndTmplSerializer( - label=_('Signatures and Templates'), required=True - ) + TENCENT_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) + TENCENT_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code')) diff --git a/apps/settings/serializers/other.py b/apps/settings/serializers/other.py index 6ca55009c..986d614fb 100644 --- a/apps/settings/serializers/other.py +++ b/apps/settings/serializers/other.py @@ -1,5 +1,3 @@ -from abc import ABCMeta - from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers @@ -17,8 +15,12 @@ class OtherSettingSerializer(serializers.Serializer): OTP_VALID_WINDOW = serializers.IntegerField(label=_("OTP valid window")) PERIOD_TASK_ENABLED = serializers.BooleanField(required=False, label=_("Enable period task")) - WINDOWS_SSH_DEFAULT_SHELL = serializers.CharField( - required=False, max_length=1024, label=_('Ansible windows default shell'), + WINDOWS_SSH_DEFAULT_SHELL = serializers.ChoiceField( + choices=[ + ('cmd', _("CMD")), + ('powershell', _("PowerShell")) + ], + label=_('Ansible windows default shell'), help_text=_('The shell type used when Windows assets perform ansible tasks') )