Beispiel #1
0
 def send_sms(self, phone_numbers: list, sign_name: str, template_code: str,
              template_param: dict, **kwargs):
     phone_numbers_str = ','.join(phone_numbers)
     send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
         phone_numbers=phone_numbers_str,
         sign_name=sign_name,
         template_code=template_code,
         template_param=json.dumps(template_param))
     try:
         logger.info(f'Alibaba sms send: '
                     f'phone_numbers={phone_numbers} '
                     f'sign_name={sign_name} '
                     f'template_code={template_code} '
                     f'template_param={template_param}')
         response = self.client.send_sms(send_sms_request)
         # 这里只判断是否成功,失败抛出异常
         if response.body.code != 'OK':
             raise JMSException(detail=response.body.message,
                                code=response.body.code)
     except TeaException as e:
         if e.code == 'SignatureDoesNotMatch':
             raise JMSException(code=e.code,
                                detail=_('Signature does not match'))
         raise JMSException(code=e.code, detail=e.message)
     return response
Beispiel #2
0
    def send_sms(self, phone_numbers: list, sign_name: str, template_code: str,
                 template_param: OrderedDict, **kwargs):
        try:
            req = models.SendSmsRequest()
            # 基本类型的设置:
            # SDK采用的是指针风格指定参数,即使对于基本类型你也需要用指针来对参数赋值。
            # SDK提供对基本类型的指针引用封装函数
            # 帮助链接:
            # 短信控制台: https://console.cloud.tencent.com/smsv2
            # sms helper: https://cloud.tencent.com/document/product/382/3773

            # 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666
            req.SmsSdkAppId = self.sdkappid
            # 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名,签名信息可登录 [短信控制台] 查看
            req.SignName = sign_name
            # 短信码号扩展号: 默认未开通,如需开通请联系 [sms helper]
            req.ExtendCode = ""
            # 用户的 session 内容: 可以携带用户侧 ID 等上下文信息,server 会原样返回
            req.SessionContext = "Jumpserver"
            # 国际/港澳台短信 senderid: 国内短信填空,默认未开通,如需开通请联系 [sms helper]
            req.SenderId = ""
            # 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
            # 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号
            req.PhoneNumberSet = phone_numbers
            # 模板 ID: 必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看
            req.TemplateId = template_code
            # 模板参数: 若无模板参数,则设置为空
            req.TemplateParamSet = list(template_param.values())
            # 通过client对象调用DescribeInstances方法发起请求。注意请求方法名与请求对象是对应的。
            # 返回的resp是一个DescribeInstancesResponse类的实例,与请求对象对应。
            logger.info(f'Tencent sms send: '
                        f'phone_numbers={phone_numbers} '
                        f'sign_name={sign_name} '
                        f'template_code={template_code} '
                        f'template_param={template_param}')

            resp = self.client.SendSms(req)

            try:
                code = resp.SendStatusSet[0].Code
                msg = resp.SendStatusSet[0].Message
            except IndexError:
                raise JMSException(code='response_bad', detail=resp)

            if code.lower() != 'ok':
                raise JMSException(code=code, detail=msg)

            return resp
        except TencentCloudSDKException as e:
            raise JMSException(code=e.code, detail=e.message)
Beispiel #3
0
 def perform_destroy(self, instance):
     user = instance.user
     role_qs = self.model.objects.filter(user=user)
     if role_qs.count() == 1:
         msg = _('{} at least one system role').format(user)
         raise JMSException(code='system_role_delete_error', detail=msg)
     return super().perform_destroy(instance)
Beispiel #4
0
 def get_org(self):
     org_id = self.request.query_params.get('org_id')
     org = Organization.get_instance(org_id)
     if not org:
         error = ('The organization `{}` does not exist'.format(org_id))
         raise JMSException(error)
     return org
Beispiel #5
0
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.get_online_session_count() > 0:
            raise JMSException(code='have_online_session',
                               detail=_('Have online sessions'))

        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #6
0
    def get_serializer_class(self):
        serializer_class = super().get_serializer_class()
        if getattr(self, 'swagger_fake_view', False):
            return serializer_class
        app_type = self.request.query_params.get('type')
        app_category = self.request.query_params.get('category')
        type_options = list(dict(models.Category.get_all_type_serializer_mapper()).keys())
        category_options = list(dict(models.Category.get_category_serializer_mapper()).keys())

        # ListAPIView 没有 action 属性
        # 不使用method属性,因为options请求时为method为post
        action = getattr(self, 'action', 'list')

        if app_type and app_type not in type_options:
            raise JMSException(
                'Invalid query parameter `type`, select from the following options: {}'
                ''.format(type_options)
            )
        if app_category and app_category not in category_options:
            raise JMSException(
                'Invalid query parameter `category`, select from the following options: {}'
                ''.format(category_options)
            )

        if action in [
            'create', 'update', 'partial_update', 'bulk_update', 'partial_bulk_update'
        ] and not app_type:
            # action: create / update
            raise JMSException(
                'The `{}` action must take the `type` query parameter'.format(action)
            )

        if app_type:
            # action: create / update / list / retrieve / metadata
            attrs_cls = models.Category.get_type_serializer_cls(app_type)
            class_name = 'ApplicationDynamicSerializer{}'.format(app_type.title())
        elif app_category:
            # action: list / retrieve / metadata
            attrs_cls = models.Category.get_category_serializer_cls(app_category)
            class_name = 'ApplicationDynamicSerializer{}'.format(app_category.title())
        else:
            attrs_cls = models.Category.get_no_password_serializer_cls()
            class_name = 'ApplicationDynamicSerializer'
        cls = type(class_name, (serializer_class,), {'attrs': attrs_cls()})
        return cls
Beispiel #7
0
 def ticket(self):
     if getattr(self, 'swagger_fake_view', False):
         return None
     ticket_id = self.request.query_params.get('ticket_id')
     ticket = Ticket.all().filter(pk=ticket_id).first()
     if not ticket:
         raise JMSException(
             'Not found Ticket object about `id={}`'.format(ticket_id))
     return ticket
Beispiel #8
0
 def __init__(self, backend=None):
     backend = backend or settings.SMS_BACKEND
     if backend not in BACKENDS:
         raise JMSException(
             code='sms_provider_not_support',
             detail=_('SMS provider not support: {}').format(backend)
         )
     m = importlib.import_module(f'.{backend or settings.SMS_BACKEND}', __package__)
     self.client = m.client.new_from_settings()
Beispiel #9
0
    def send_verify_code(self, phone_number, code):
        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))
Beispiel #10
0
    def update_serial_num_if_need(self):
        if self.serial_num:
            return

        try:
            self.serial_num = self.construct_serial_num()
            self.save(update_fields=('serial_num',))
        except IntegrityError as e:
            if e.args[0] == 1062:
                # 虽然做了 `select_for_update` 但是每天的第一条工单仍可能造成冲突
                # 但概率小,这里只报错,用户重新提交即可
                raise JMSException(detail=_('Please try again'), code='please_try_again')

            raise e
Beispiel #11
0
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        tencent_secret_id = serializer.validated_data['TENCENT_SECRET_ID']
        tencent_secret_key = serializer.validated_data.get(
            'TENCENT_SECRET_KEY')
        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')

        if not test_phone:
            raise JMSException(code='test_phone_required',
                               detail=_('test_phone is required'))

        if not tencent_secret_key:
            secret = Setting.objects.filter(name='TENCENT_SECRET_KEY').first()
            if secret:
                tencent_secret_key = secret.cleaned_value

        tencent_secret_key = tencent_secret_key or ''

        try:
            client = TencentSMS(secret_id=tencent_secret_id,
                                secret_key=tencent_secret_key,
                                sdkappid=tencent_sdkappid)

            client.send_sms(phone_numbers=[test_phone],
                            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')})
        except APIException as e:
            try:
                error = e.detail['errmsg']
            except:
                error = e.detail
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data={'error': error})
Beispiel #12
0
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        alibaba_access_key_id = serializer.validated_data[
            'ALIBABA_ACCESS_KEY_ID']
        alibaba_access_key_secret = serializer.validated_data.get(
            'ALIBABA_ACCESS_KEY_SECRET')
        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:
            raise JMSException(code='test_phone_required',
                               detail=_('test_phone is required'))

        if not alibaba_access_key_secret:
            secret = Setting.objects.filter(
                name='ALIBABA_ACCESS_KEY_SECRET').first()
            if secret:
                alibaba_access_key_secret = secret.cleaned_value

        alibaba_access_key_secret = alibaba_access_key_secret or ''

        try:
            client = AlibabaSMS(access_key_id=alibaba_access_key_id,
                                access_key_secret=alibaba_access_key_secret)

            client.send_sms(phone_numbers=[test_phone],
                            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')})
        except APIException as e:
            try:
                error = e.detail['errmsg']
            except:
                error = e.detail
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data={'error': error})
Beispiel #13
0
 def check_category_allowed(obj):
     if not obj.category_is_remote_app:
         raise JMSException(
             'The request instance(`{}`) is not of category `remote_app`'.format(obj.category)
         )