From 818c0861685de771b3c3fa1212592798d74eec82 Mon Sep 17 00:00:00 2001 From: "liusi.xbw" Date: Mon, 11 Oct 2021 16:58:27 +0800 Subject: [PATCH] WIP: new risk implements --- .../interceptors/riskInterceptor/dialog.tsx | 119 ++++++++++++++++++ .../src/interceptors/riskInterceptor/form.tsx | 28 ++--- .../riskInterceptor/getVerifyInformation.tsx | 74 ----------- .../riskInterceptor/handleDoubleConfirm.tsx | 8 +- .../src/interceptors/riskInterceptor/type.ts | 47 +++++++ .../stories/demo/riskDialog.tsx | 30 +++++ .../stories/index.stories.tsx | 6 +- packages/xconsole/xconsole.json | 2 +- 8 files changed, 216 insertions(+), 98 deletions(-) create mode 100644 packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/dialog.tsx delete mode 100644 packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/getVerifyInformation.tsx create mode 100644 packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/type.ts create mode 100644 packages/console-utils/xconsole-service/stories/demo/riskDialog.tsx diff --git a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/dialog.tsx b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/dialog.tsx new file mode 100644 index 00000000..ca5b5de5 --- /dev/null +++ b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/dialog.tsx @@ -0,0 +1,119 @@ +import ReactDOM from 'react-dom' +import React, { Component } from 'react'; +import { Dialog, ConfigProvider } from '@alicloud/console-components'; + +import Form from './form'; +import messages from './messages'; +import { RiskDialogProps, RiskDialogOptions, IVerifyInfo } from './type'; + +class RiskDialog extends Component { + state = { + visible: true, + verifyCode: '', + requestId: '', + }; + + constructor(props: RiskDialogProps) { + super(props) + this.state.requestId = props.formProps?.requestId; + } + + close = () => { + this.setState({ visible: false }); + }; + + render = () => { + const { onConfirm, onCancel, onClose, formProps, ...others } = this.props; + const { visible, verifyCode, requestId } = this.state; + + return ( + { + this.close(); + onCancel(e); + }} + onOk={() => { + this.close(); + onConfirm({ verifyCode, requestId }) + }} + onClose={(...args) => { + this.close(); + onClose(...args); + }} + > +
{ + this.setState({requestId}) + } + } + setVerifyCode={ + (verifyCode) => { + this.setState({verifyCode}) + } + } + /> +
+ ) + } +} + +export const show = (config: RiskDialogOptions) => { + return new window.Promise((resolve, reject) => { + const container = document.createElement('div'); + const unmount = () => { + ReactDOM.unmountComponentAtNode(container); + container.parentNode.removeChild(container); + }; + document.body.appendChild(container); + // @ts-ignore + const newContext = ConfigProvider.getContext(); + const { verifyType } = config; + + const handleVerifyCodeConfirm = () => { + ({ verifyCode, requestId }) => { + if (verifyType === 'ga' && verifyCode) { + resolve({ vCode: verifyCode }); + } + if (requestId && verifyCode) { + resolve({ + reqId: requestId, + vCode: verifyCode, + }); + } + console.warn('[getVerifyInformation] failed: ', requestId, verifyCode ); + } + } + + ReactDOM.render( + + { + reject(new Error('Verification has been canceled!')); + }} + onClose={() => { + reject(new Error('Verification has been canceled!')); + }} + formProps={{ ...config }} + afterClose={unmount} + /> + , + container + ); + }); +}; + +export default { + show +}; \ No newline at end of file diff --git a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/form.tsx b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/form.tsx index caa57756..7aa9f825 100644 --- a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/form.tsx +++ b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/form.tsx @@ -4,6 +4,7 @@ import { Button, Input, Grid, Form } from '@alicloud/console-components'; import { getSecToken, getUmid, getCollina } from '../../utils/index'; import searchParamsInterceptor from '../paramsInterceptor/index'; import messages from './messages'; +import { RiskOption, RiskUrlOption } from './type'; const { Col, Row } = Grid; const ItemLayout = { @@ -14,17 +15,16 @@ const axiosInstance = axios.create(); axiosInstance.interceptors.request.use(searchParamsInterceptor); -interface IProps { - options?: { - codeType?: string; - verifyType?: string; - verifyDetail?: any; - isVerifyCodeValid?: any; - }; +export interface IProps { + codeType?: string; + verifyType?: string; + verifyDetail?: any; + isVerifyCodeValid?: boolean; + requestId?: string; setVerifyCode?: (value: string) => void; setRequestId?: (id: any) => void; onError?: (value: any) => void; - risk: any; + riskConfig: RiskOption; } interface IState { @@ -35,7 +35,7 @@ interface IState { class VerifyForm extends Component { timer: number | null; - verifyUrl: { [key: string]: string }; + verifyUrl: RiskUrlOption; constructor(props: IProps) { super(props); @@ -44,7 +44,7 @@ class VerifyForm extends Component { isCountdownStarted: false, countdown: 0, }; - this.verifyUrl = props.risk.url; + this.verifyUrl = props.riskConfig.url; this.onInputChange = this.onInputChange.bind(this); this.onGenerateVerifyCode = this.onGenerateVerifyCode.bind(this); this.startCountdownTimer = this.startCountdownTimer.bind(this); @@ -64,7 +64,7 @@ class VerifyForm extends Component { async onGenerateVerifyCode(): Promise { this.startCountdownTimer(); - const { options: { codeType, verifyType } = {}, setRequestId } = this.props; + const { codeType, verifyType, setRequestId } = this.props; const reqData = { codeType, verifyType, @@ -91,10 +91,7 @@ class VerifyForm extends Component { setRequestId?.(resData.requestId); // 保存发送验证码请求的 requestId } catch (e) { - // eslint-disable-next-line no-console console.error('[onGenerateVerifyCode] failed: ', e.message); - // this.props.onError(e) - // setRequestId('Fake requestId') } } @@ -123,7 +120,7 @@ class VerifyForm extends Component { render(): JSX.Element { const { - options: { verifyType = '', verifyDetail, isVerifyCodeValid } = {}, + verifyType = '', verifyDetail, isVerifyCodeValid } = this.props; const verifyMessages = { @@ -132,7 +129,6 @@ class VerifyForm extends Component { }; const { isCountdownStarted, countdown } = this.state; - return ( diff --git a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/getVerifyInformation.tsx b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/getVerifyInformation.tsx deleted file mode 100644 index 9a7bde25..00000000 --- a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/getVerifyInformation.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React from 'react'; -import { Dialog } from '@alicloud/console-components'; -import Form from './form'; -import messages from './messages'; - -export interface IVerifyInfo { - reqId?: string; - vCode?: string; -} - -function getVerifyInformation(options: any): Promise { - return new Promise((resolve, reject) => { - // eslint-disable-next-line prefer-const - let { lastRequestId: requestId, risk, ...rest } = options; - let verifyCode: any; - - function setRequestId(val: any): void { - requestId = val; - } - function setVerifyCode(val: string): void { - verifyCode = val; - } - - const { verifyType } = options; - const { title } = messages[verifyType]; - - try { - Dialog.confirm({ - // 弹出对话框 - title, - content: ( - - ), - onOk: () => { - if (verifyType === 'ga' && verifyCode) { - return resolve({ vCode: verifyCode }); - } - if (requestId && verifyCode) { - return resolve({ - reqId: requestId, - vCode: verifyCode, - }); - } - console.warn( - // eslint-disable-line no-console - '[getVerifyInformation] failed: ', - requestId, - verifyCode - ); - - return false; - }, - onCancel: () => { - reject(new Error('Verification has been canceled!')); - }, - onClose: () => { - reject(new Error('Verification has been canceled!')); - }, - needWrapper: false, - }); - } catch (e) { - console.log('[getVerifyInformation] failed: ', e); - reject(e); - } - }); -} - -export default getVerifyInformation; diff --git a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/handleDoubleConfirm.tsx b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/handleDoubleConfirm.tsx index f3eb3fe5..32f72e3a 100644 --- a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/handleDoubleConfirm.tsx +++ b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/handleDoubleConfirm.tsx @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios'; import { URLSearchParams } from '../paramsInterceptor/index'; -import getVerifyInformation from './getVerifyInformation'; +import RiskDialog from './dialog'; import { guideToVerificationMethodSetting, guideToVerificationDetailSetting, @@ -58,11 +58,11 @@ async function handleDoubleConfirm( verifyType, verifyDetail, codeType, - lastRequestId, - risk, + requestId: lastRequestId, + riskConfig: risk, }; try { - const { reqId, vCode } = await getVerifyInformation(options); + const { reqId, vCode } = await RiskDialog.show(options); requestId = reqId; verifyCode = vCode; lastRequestId = requestId; diff --git a/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/type.ts b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/type.ts new file mode 100644 index 00000000..38ef531c --- /dev/null +++ b/packages/console-utils/xconsole-service/src/interceptors/riskInterceptor/type.ts @@ -0,0 +1,47 @@ +import { IProps as FormProps } from './form'; +import { DialogProps } from '@alifd/next/lib/dialog'; + +export interface IVerifyInfo { + reqId?: string; + vCode?: string; +} + +export interface RiskUrlOption { + generateVerificationCode: string; + setVerificationMethod: string; + changeVerificationMethod: string; + bindMobileHelp: string; +} + +export interface RiskOption { + code: { + success: string; + doubleConfirm: string; + forbidden: string; + verifyCodeInvalid: string; + }; + url: RiskUrlOption; +} + +export interface RiskDialogOptions { + requestId?: string; + // 风控码 + codeType: string; + // + mteeCode: "aliyun_console"; + // 验证详情提示 + verifyDetail: string; + // 风控类型 + verifyType: "sms" | 'ga' | 'mfa'; + + // 是否为正确的风控错误码 + isVerifyCodeValid: boolean; + + // Risk 的配置 + riskConfig: RiskOption; +} + +export interface RiskDialogProps extends DialogProps { + onConfirm: ({ verifyCode, requestId }) => void; + formProps?: FormProps; +} \ No newline at end of file diff --git a/packages/console-utils/xconsole-service/stories/demo/riskDialog.tsx b/packages/console-utils/xconsole-service/stories/demo/riskDialog.tsx new file mode 100644 index 00000000..5ef05587 --- /dev/null +++ b/packages/console-utils/xconsole-service/stories/demo/riskDialog.tsx @@ -0,0 +1,30 @@ +import { useEffect } from 'react'; +import Dialog from '../../src/interceptors/riskInterceptor/dialog'; + + +export default () => { + useEffect(() => { + Dialog.show({ + codeType: "ims_user_delete", + mteeCode: "aliyun_console", + verifyDetail: "180****5420", + verifyType: "sms", + isVerifyCodeValid: true, + riskConfig: { + code: { + success: '200', + doubleConfirm: 'FoundRiskAndDoubleConfirm', + forbidden: 'FoundRiskAndTip', + verifyCodeInvalid: 'verifyCodeInvalid', + }, + url: { + generateVerificationCode: '/risk/sendVerifyMessage.json', + setVerificationMethod: 'https://account.console.aliyun.com/#/secure', + changeVerificationMethod: 'https://account.console.aliyun.com/#/secure', + bindMobileHelp: 'https://account.console.aliyun.com', + }, + }, + }) + }, []) + return null; +} \ No newline at end of file diff --git a/packages/console-utils/xconsole-service/stories/index.stories.tsx b/packages/console-utils/xconsole-service/stories/index.stories.tsx index 8cffc98b..3072f042 100644 --- a/packages/console-utils/xconsole-service/stories/index.stories.tsx +++ b/packages/console-utils/xconsole-service/stories/index.stories.tsx @@ -1,10 +1,10 @@ import React, { useEffect } from 'react'; import { select, withKnobs } from '@storybook/addon-knobs'; -// import withAxiosDecorator from 'storybook-axios'; import { storiesOf } from '@storybook/react'; import { createService, useOpenApi, useRoaApi, defaultAxiosRequest } from '../src/index' import { ApiType } from '../src/const'; import '@alicloud/console-components/dist/wind.css' +import RiskDialog from './demo/riskDialog'; // @ts-ignore defaultAxiosRequest.interceptors.request.handlers.unshift({ @@ -17,8 +17,6 @@ defaultAxiosRequest.interceptors.request.handlers.unshift({ storiesOf('XConsole Service', module) .addDecorator(withKnobs) - // @ts-ignore - // .addDecorator(withAxiosDecorator(defaultAxiosRequest)) .add('AppCode', () => { const action = select('action', ['DescribeInstance', 'DescribeAPI'], 'DescribeInstance') const { data, error } = useOpenApi('consoledemo', action, null, { throwDoubleConfirmError: true }) @@ -45,3 +43,5 @@ storiesOf('XConsole Service', module) return
}) + + .add('riskDialog', RiskDialog) diff --git a/packages/xconsole/xconsole.json b/packages/xconsole/xconsole.json index 545c776b..60d499ea 100644 --- a/packages/xconsole/xconsole.json +++ b/packages/xconsole/xconsole.json @@ -1 +1 @@ -{"version":"2.3.33"} \ No newline at end of file +{"version":"2.3.35"} \ No newline at end of file