From 640b27b533e892b6dc76f0c3443b69b0de78792f Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 10 Nov 2023 15:18:05 +0800 Subject: [PATCH 1/4] add callback page --- src/auth/utils.js | 5 +- src/pages/iAmSmart/FailCallback/index.js | 66 +++++++++++++++++++++ src/pages/iAmSmart/SuccessCallback/index.js | 66 +++++++++++++++++++++ src/routes/LoginRoutes.js | 16 ++++- 4 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 src/pages/iAmSmart/FailCallback/index.js create mode 100644 src/pages/iAmSmart/SuccessCallback/index.js diff --git a/src/auth/utils.js b/src/auth/utils.js index e5440d9..9c99e55 100644 --- a/src/auth/utils.js +++ b/src/auth/utils.js @@ -13,7 +13,10 @@ export const hostPath = `http://${hostname}:${hostPort}`; export const apiPath = `${hostPath}/api`; // export const apiPath = `/api`; export const paymentPath = `http://pnspsdev.gld.gov.hk/payment`; -export const iAmSmartPath = `https://`; +export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; + +// clientId : cf61fa7c121e4869966f69c8694b1cd2 + export const isUserLoggedIn = () => { diff --git a/src/pages/iAmSmart/FailCallback/index.js b/src/pages/iAmSmart/FailCallback/index.js new file mode 100644 index 0000000..e908b83 --- /dev/null +++ b/src/pages/iAmSmart/FailCallback/index.js @@ -0,0 +1,66 @@ +// material-ui +import { + Grid, + Typography, + Stack, +} from '@mui/material'; +import * as React from "react"; + +import Loadable from 'components/Loadable'; +const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: '100%', + height: '100%', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const Index = () => { + + const [onReady, setOnReady] = React.useState(false); + + React.useEffect(() => { + setOnReady(true); + }, []); + + return ( + !onReady ? + + : + + +
+ + iAmSmart 登入失敗 + +
+
+ {/*row 1*/} + + +
+ + + + 連接 iAM Smart 時出現錯誤,請重試。 + + + +
+
+
+ {/*row 2*/} +
+ + + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/pages/iAmSmart/SuccessCallback/index.js b/src/pages/iAmSmart/SuccessCallback/index.js new file mode 100644 index 0000000..15ff2e3 --- /dev/null +++ b/src/pages/iAmSmart/SuccessCallback/index.js @@ -0,0 +1,66 @@ +// material-ui +import { + Grid, + Typography, + Stack, +} from '@mui/material'; +import * as React from "react"; + +import Loadable from 'components/Loadable'; +const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: '100%', + height: '100%', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const Index = () => { + + const [onReady, setOnReady] = React.useState(false); + + React.useEffect(() => { + setOnReady(true); + }, []); + + return ( + !onReady ? + + : + + +
+ + iAmSmart 成功登入 + +
+
+ {/*row 1*/} + + +
+ + + + iAmSmart 成功登入 + + + +
+
+
+ {/*row 2*/} +
+ + + ); +}; + +export default Index; diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index a7b48af..99c9bc4 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -11,6 +11,10 @@ const AuthRegister = Loadable(lazy(() => import('pages/authentication/RegisterCu const RegisterForm = Loadable(lazy(() => import('pages/authentication/Register'))); const BusRegisterForm = Loadable(lazy(() => import('pages/authentication/BusRegister'))); const ErrorPage = Loadable(lazy(() => import('pages/extra-pages/ErrorPage'))); +const IAmSmart_FailCallback = Loadable(lazy(() => import('pages/iAmSmart/FailCallback'))); +const IAmSmart_SuccessCallback = Loadable(lazy(() => import('pages/iAmSmart/SuccessCallback'))); + +//TODO: this page for testing only, please remove at prod const TestMailPage = Loadable(lazy(() => import('pages/pnspsNotifyTest'))); // ==============================|| AUTH ROUTING ||============================== // @@ -19,6 +23,10 @@ const LoginRoutes = { path: '/', element: , children: [ + {//TODO: this page for testing only, please remove at prod + path: 'testMailPage', + element: + }, { path: 'login', element: @@ -40,8 +48,12 @@ const LoginRoutes = { element: }, { - path: 'testMailPage', - element: + path: 'iamsmart/loginfailback', + element: + }, + { + path: 'iamsmart/logincallback', + element: } ] }; From cc410207390d2450ce72833faa759049dc0a5abd Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 10 Nov 2023 16:59:15 +0800 Subject: [PATCH 2/4] add i am smart pop up --- src/pages/authentication/RegisterCustom.js | 171 ++++++++++++++------- 1 file changed, 116 insertions(+), 55 deletions(-) diff --git a/src/pages/authentication/RegisterCustom.js b/src/pages/authentication/RegisterCustom.js index b478d0c..eb6a760 100644 --- a/src/pages/authentication/RegisterCustom.js +++ b/src/pages/authentication/RegisterCustom.js @@ -1,76 +1,137 @@ // material-ui -import {Link, Button, Card , Box, Grid } from '@mui/material'; +import { + Dialog, DialogTitle, DialogContent, DialogActions, + Link, Button, Card, Box, Grid +} from '@mui/material'; import Typography from '@mui/material/Typography'; import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; import banner from 'assets/images/bg_ml.jpg'; import { Stack } from '../../../node_modules/@mui/material/index'; +import * as React from 'react'; + // ================================|| LOGIN ||================================ // -const RegisterCustom = () => ( - - - banner -
- *': { - flexGrow: 1, - flexBasis: '50%' - }, - backgroundColor: "secondary" - }} - - > - - - - 立即成為憲報刊登公告用戶 - 只需4-5分鐘 - - - - - - 個人用戶 - - - - - 你可點擊「智方便」按鈕,系統會自動輸入個人資料,或自行輸入個人資料,以即時啟動憲報刊登公告帳戶。 -
如欲使用「智方便」提供個人資料,請先下載「智方便」流動應用程式並登記成為「智方便」用戶。 -
- 了解更多 -
+const RegisterCustom = () => { + + const [isPopUp, setIsPopUp] = React.useState(false); + - + const registerWithIAmSmart = () => { + setIsPopUp(true); + } + + + return ( + + banner +
+ *': { + flexGrow: 1, + flexBasis: '50%' + }, + backgroundColor: "secondary" + }} + + > + + + + 立即成為憲報刊登公告用戶 + 只需4-5分鐘 + + + + + + 個人用戶 + - + + + 你可點擊「智方便」按鈕,系統會自動輸入個人資料,或自行輸入個人資料,以即時啟動憲報刊登公告帳戶。 +
如欲使用「智方便」提供個人資料,請先下載「智方便」流動應用程式並登記成為「智方便」用戶。 +
+ 了解更多 +
- - 需上載身份證明文件數碼檔案以進行網上申請。 -
如:香港身份證; 護照; 中國內地身份證; 專業執業証書等 + + + + + + 需上載身份證明文件數碼檔案以進行網上申請。 +
如:香港身份證; 護照; 中國內地身份證; 專業執業証書等 +
+
+ + 機構/公司用戶 + + + 需上載以下任何一份證明文件以進行網上申請。 +
如:商業登記證;專業執業證書 +
+
+
+
+
+
+
+ setIsPopUp(false)} > + + + + 授權「智方便」提供個人資料 + + + 為完成開戶並建立與「智方便」的連接,請授權「智方便」提供以下個人資料: + + + + + + + - 中文姓名 + + + - 英文姓名 + + + - 身份證號碼 + + + - 性別 - - 機構/公司用戶 - - - 需上載以下任何一份證明文件以進行網上申請。 -
如:商業登記證;專業執業證書 + + + - 中文姓名 + + + - 英文姓名 + + + - 身份證號碼 + + + - 性別
-
-
-
-
-
+ + + + + + + ); -); +}; export default RegisterCustom; From a7518f504c8bbfe18e706f3160955692f5406d41 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 14 Nov 2023 17:09:04 +0800 Subject: [PATCH 3/4] add authcallback --- src/auth/utils.js | 4 +- src/pages/authentication/RegisterCustom.js | 3 +- src/pages/iAmSmart/AuthCallback/index.js | 176 +++++++++++++++++++++ src/routes/LoginRoutes.js | 5 + 4 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 src/pages/iAmSmart/AuthCallback/index.js diff --git a/src/auth/utils.js b/src/auth/utils.js index c37cbb6..5fa664e 100644 --- a/src/auth/utils.js +++ b/src/auth/utils.js @@ -10,8 +10,8 @@ export const hostname = 'localhost'; const hostPort = '8090'; export const hostPath = `http://${hostname}:${hostPort}`; //export const apiPath = `http://192.168.0.112:8090/api`; -export const apiPath = `${hostPath}/api`; -// export const apiPath = `/api`; +//export const apiPath = `${hostPath}/api`; + export const apiPath = `/api`; export const paymentPath = `http://pnspsdev.gld.gov.hk/payment`; export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; diff --git a/src/pages/authentication/RegisterCustom.js b/src/pages/authentication/RegisterCustom.js index 47d5f3f..33f1558 100644 --- a/src/pages/authentication/RegisterCustom.js +++ b/src/pages/authentication/RegisterCustom.js @@ -25,11 +25,12 @@ const RegisterCustom = () => { } const getQRWithIAmSmart = () => { + let callbackUrl = "https://"+window.location.hostname+"/iamsmart/logincallback"; let url = iAmSmartPath + "/api/v1/auth/getQR" + "?clientID=" + clientId + "&responseType=code" +"&source=" + getBowerType() - +"&redirectURI=" + +"&redirectURI="+encodeURIComponent(callbackUrl) +"&scope=eidapi_formFilling" +"&lang=zh-HK"//en-US, zh-HK, or zh-CN //+"&state=" diff --git a/src/pages/iAmSmart/AuthCallback/index.js b/src/pages/iAmSmart/AuthCallback/index.js new file mode 100644 index 0000000..404fe2c --- /dev/null +++ b/src/pages/iAmSmart/AuthCallback/index.js @@ -0,0 +1,176 @@ +// material-ui +import { + Grid, + Typography, + Stack, + Card, + FormHelperText, + InputLabel, OutlinedInput, +} from '@mui/material'; +import * as React from "react"; +import { useFormik, FormikProvider } from 'formik'; +import * as yup from 'yup'; + +import Loadable from 'components/Loadable'; +const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: '100%', + height: '100%', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const Index = () => { + + const [onReady, setOnReady] = React.useState(false); + const [checkUsername, setCheckUsername] = React.useState(false); + const [props, setProps] = React.useState({}); + + React.useEffect(() => { + setOnReady(true); + setProps({}); + }, []); + + function displayErrorMsg(errorMsg) { + return {errorMsg} + } + + const formik = useFormik({ + initialValues: ({ + username: '', + enName: '', + email: '', + address1: '', + address2: '', + address3: '', + password: '', + phone: '', + phoneCountryCode: '852', + }), + + validationSchema: yup.object().shape({ + username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg('請輸入用戶名稱')) + .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg("用戶名稱不包含特殊字符") }) + .matches(/^\S*$/, { message: displayErrorMsg('用戶名稱不包含空格') }), + enName: yup.string().max(255).required(displayErrorMsg('請輸入英文姓名')), + chName: yup.string().max(255).required(displayErrorMsg('請輸入中文姓名')), + address1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')), + address2: yup.string().max(255).required(displayErrorMsg('請輸入第二行地址')), + address3: yup.string().max(255).required(displayErrorMsg('請輸入第三行地址')), + email: yup.string().email(displayErrorMsg('請輸入電郵格式')).max(255).required(displayErrorMsg('請輸入電郵')), + phoneCountryCode: yup.string().min(2, displayErrorMsg('請輸入最少2位數字')).required(displayErrorMsg('請輸入國際區號')), + phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')), + }, ['username']), + + }); + + + return ( + !onReady ? + + : + + + +
+ + iAmSmart 登記 + +
+
+ {/*row 1*/} + + + *': { + flexGrow: 1, + flexBasis: '50%' + }, + backgroundColor: "secondary", + p:8, + pl:16, + pr:16 + }} + > + + + +
+ 成為個人用戶 +
+ 註有*的項目必須輸入資料 + 用戶資料 + {/* + Already have an account? + */} +
+
+ + + + + + + 用戶登入名稱 + * + + + { + setCheckUsername(false) + props.username = e.target.value + formik.handleChange(e) + }} + placeholder="用戶登入名稱" + fullWidth + error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)} + onBlur={formik.handleBlur} + inputProps={{ + onKeyDown: (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + {formik.touched.username && formik.errors.username && ( + + {formik.errors.username} + + )} + {checkUsername && ( + + 此用戶登入名稱已被注冊,請使用其他用戶登入名稱 + + )} + + + + + +
+
+
+
+ {/*row 2*/} +
+
+ + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index 87f0fc9..3fc8167 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -13,6 +13,7 @@ const BusRegisterForm = Loadable(lazy(() => import('pages/authentication/BusRegi const ErrorPage = Loadable(lazy(() => import('pages/extra-pages/ErrorPage'))); const IAmSmart_FailCallback = Loadable(lazy(() => import('pages/iAmSmart/FailCallback'))); const IAmSmart_SuccessCallback = Loadable(lazy(() => import('pages/iAmSmart/SuccessCallback'))); +const IAmSmart_AuthCallback = Loadable(lazy(() => import('pages/iAmSmart/AuthCallback'))); //TODO: this page for testing only, please remove at prod const TestMailPage = Loadable(lazy(() => import('pages/pnspsNotifyTest'))); @@ -48,6 +49,10 @@ const LoginRoutes = { path: 'error', element: }, + { + path: 'iamsmart/authcallback', + element: + }, { path: 'iamsmart/loginfailback', element: From 192162611583560a1670da4d11369d3f3a7a9b69 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 16 Nov 2023 12:20:26 +0800 Subject: [PATCH 4/4] add i am smart --- src/auth/utils.js | 54 ++++++++++++++-------- src/pages/authentication/RegisterCustom.js | 6 +-- src/pages/iAmSmart/AuthCallback/index.js | 13 +++++- src/routes/LoginRoutes.js | 2 +- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/auth/utils.js b/src/auth/utils.js index 9dcdf91..62e8260 100644 --- a/src/auth/utils.js +++ b/src/auth/utils.js @@ -10,42 +10,58 @@ export const hostname = 'localhost'; const hostPort = '8090'; export const hostPath = `http://${hostname}:${hostPort}`; //export const apiPath = `http://192.168.0.112:8090/api`; -<<<<<<< HEAD -//export const apiPath = `${hostPath}/api`; - export const apiPath = `/api`; -======= + export const apiPath = `${hostPath}/api`; //export const apiPath = `/api`; ->>>>>>> master + export const paymentPath = `http://pnspsdev.gld.gov.hk/payment`; export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; export const clientId = "cf61fa7c121e4869966f69c8694b1cd2"; -export const getBowerType=()=>{ + +export const iAmSmartCallbackPath = () => { + let hostname = window.location.hostname; + if (hostname.match("localhost")) { + hostname = "pnspsuat.gld.gov.hk"; + } + return hostname; +}; + +export const getNonce = () => { + let hostname = window.location.hostname; + if (hostname.match("localhost")) { + hostname = "pnspsuat.gld.gov.hk"; + } + return hostname; +}; + + + +export const getBowerType = () => { console.log(navigator.userAgent) // const regex = /Mobi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Mi|huawei|Opera Mini|SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i; // if(!regex.test(navigator.userAgent)) if (navigator.userAgent.indexOf("Edg") != -1) { - if(navigator.userAgent.match(/Android/i)) return "Android_Edge" - if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Edge" + if (navigator.userAgent.match(/Android/i)) return "Android_Edge" + if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Edge" return "PC_Browser" - }else if(navigator.userAgent.indexOf("Chrome") != -1){ - if(navigator.userAgent.match(/Android/i)) return "Android_Chrome" - if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome" + } else if (navigator.userAgent.indexOf("Chrome") != -1) { + if (navigator.userAgent.match(/Android/i)) return "Android_Chrome" + if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome" return "PC_Browser" - }else if(navigator.userAgent.indexOf("Safari") != -1){ - if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Safari" + } else if (navigator.userAgent.indexOf("Safari") != -1) { + if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Safari" return "PC_Browser" - }else if(navigator.userAgent.indexOf("Firefox") != -1){ - if(navigator.userAgent.match(/Android/i)) return "Android_Firefox" - if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Firefox" + } else if (navigator.userAgent.indexOf("Firefox") != -1) { + if (navigator.userAgent.match(/Android/i)) return "Android_Firefox" + if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Firefox" return "PC_Browser" - }else if(navigator.userAgent.match(/SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i)){ + } else if (navigator.userAgent.match(/SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i)) { return "Android_Samsung" - }else if(navigator.userAgent.match(/huawei/i)){ + } else if (navigator.userAgent.match(/huawei/i)) { return "Android_Huawei" - }else if(navigator.userAgent.match(/Mi/i)){ + } else if (navigator.userAgent.match(/Mi/i)) { return "Android_Xiaomi" } return "PC_Browser"; diff --git a/src/pages/authentication/RegisterCustom.js b/src/pages/authentication/RegisterCustom.js index 33f1558..2ed113a 100644 --- a/src/pages/authentication/RegisterCustom.js +++ b/src/pages/authentication/RegisterCustom.js @@ -9,7 +9,7 @@ import Typography from '@mui/material/Typography'; import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; import banner from 'assets/images/bg_ml.jpg'; import { Stack } from '../../../node_modules/@mui/material/index'; -import { iAmSmartPath, clientId, getBowerType } from 'auth/utils' +import { iAmSmartPath, clientId, getBowerType , iAmSmartCallbackPath} from 'auth/utils' import * as React from 'react'; @@ -25,13 +25,13 @@ const RegisterCustom = () => { } const getQRWithIAmSmart = () => { - let callbackUrl = "https://"+window.location.hostname+"/iamsmart/logincallback"; + let callbackUrl = "https://"+iAmSmartCallbackPath()+"/iamsmart/authcallback"; let url = iAmSmartPath + "/api/v1/auth/getQR" + "?clientID=" + clientId + "&responseType=code" +"&source=" + getBowerType() +"&redirectURI="+encodeURIComponent(callbackUrl) - +"&scope=eidapi_formFilling" + +"&scope="+encodeURIComponent("eidapi_auth eidapi_profiles") +"&lang=zh-HK"//en-US, zh-HK, or zh-CN //+"&state=" +"&brokerPage=false" diff --git a/src/pages/iAmSmart/AuthCallback/index.js b/src/pages/iAmSmart/AuthCallback/index.js index 404fe2c..b626731 100644 --- a/src/pages/iAmSmart/AuthCallback/index.js +++ b/src/pages/iAmSmart/AuthCallback/index.js @@ -10,6 +10,8 @@ import { import * as React from "react"; import { useFormik, FormikProvider } from 'formik'; import * as yup from 'yup'; +import { useParams } from "react-router-dom"; +//import { iAmSmartPath, clientId, getBowerType , iAmSmartCallbackPath} from 'auth/utils' import Loadable from 'components/Loadable'; const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); @@ -29,15 +31,22 @@ const BackgroundHead = { const Index = () => { + const params = useParams(); const [onReady, setOnReady] = React.useState(false); const [checkUsername, setCheckUsername] = React.useState(false); const [props, setProps] = React.useState({}); React.useEffect(() => { - setOnReady(true); - setProps({}); + if(params.code){ + setOnReady(true); + setProps({}); + } }, []); + // function loadIAmSmartProfile(){ + + // } + function displayErrorMsg(errorMsg) { return {errorMsg} } diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index 3fc8167..d0adeb1 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -54,7 +54,7 @@ const LoginRoutes = { element: }, { - path: 'iamsmart/loginfailback', + path: 'iamsmart/loginfallback', element: }, {