diff --git a/README.md b/README.md index aba1f360..f387bb1c 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ TaaS App is done using Single SPA micro-frontend architecture https://single-spa ### Local Authentication First of all, to authenticate locally we have to run a local authentication service. + - Clone this repository into `taas-app`. - Inside the folder `taas-app/local/login-locally` run `npm run start`. - You would need npm 5+ for it. This would start a local sever on port 5000 which could be used for local Authentication. @@ -76,36 +77,36 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t 1. Run **Frame** App: - ```sh - git clone https://github.com/topcoder-platform/micro-frontends-frame.git - cd micro-frontends-frame - # inside folder "micro-frontends-frame" run: + ```sh + git clone https://github.com/topcoder-platform/micro-frontends-frame.git + cd micro-frontends-frame + # inside folder "micro-frontends-frame" run: - nvm use # or make sure to use Node 10 - npm i # to install dependencies + nvm use # or make sure to use Node 10 + npm i # to install dependencies - # set environment variables: + # set environment variables: - export APPMODE="development" - export APPENV="local-multi" + export APPMODE="development" + export APPENV="local-multi" - npm run local-server + npm run local-server - # this would start frame server on http://localhost:3000 - ``` + # this would start frame server on http://localhost:3000 + ``` - open one more terminal window in the same folder and run: + open one more terminal window in the same folder and run: - ```sh - # set environment variables: + ```sh + # set environment variables: - export APPMODE="development" - export APPENV="local-multi" + export APPMODE="development" + export APPENV="local-multi" - npm run local-client + npm run local-client - # this host frame client code on http://localhost:8080 - ``` + # this host frame client code on http://localhost:8080 + ``` 2. Run **Navbar** micro-app: @@ -135,6 +136,10 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t nvm use # or make sure to use Node 10 npm i # to install dependencies + # set environment variables: + + export STRIPE_PUBLIC_KEY="" + npm run dev # this host TaaS App as http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js @@ -142,16 +147,16 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t 4. Now we have to update the `micro-frontends-frame` app to show our local version of TaaS App, instead of remote one. Update file `micro-frontends-frame/config/micro-frontends-config-local.json`: - ```js - // replace line - "@topcoder/micro-frontends-teams": "https://platform.topcoder-dev.com/taas-app/topcoder-micro-frontends-teams.js", + ```js + // replace line + "@topcoder/micro-frontends-teams": "https://platform.topcoder-dev.com/taas-app/topcoder-micro-frontends-teams.js", - // with line: - "@topcoder/micro-frontends-teams": "http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js", - ``` + // with line: + "@topcoder/micro-frontends-teams": "http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js", + ``` - Now open in the browser http://localhost:8080/taas/myteams. - If you are not logged-in yet, you should be redirected to the login page. - If you cannot see the application and redirect doesn't happen, make sure that file "http://local.topcoder-dev.com:8501/taas-app/topcoder-micro-frontends-teams.js" is loaded successfully in the Network tab. -Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/micro-frontends-navbar-app. \ No newline at end of file +Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/micro-frontends-navbar-app. diff --git a/build.sh b/build.sh index 7d73d2b9..250e113f 100755 --- a/build.sh +++ b/build.sh @@ -4,6 +4,7 @@ APP_NAME=$1 UPDATE_CACHE="" docker build -f docker/Dockerfile -t $APP_NAME:latest \ +--build-arg STRIPE_PUBLIC_KEY=$STRIPE_PUBLIC_KEY \ --build-arg APPMODE=$APPMODE \ --build-arg APPENV=$APPENV . diff --git a/docker/Dockerfile b/docker/Dockerfile index a3565335..00924af2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,9 +3,11 @@ FROM node:10 ARG APPMODE ARG APPENV +ARG STRIPE_PUBLIC_KEY ENV APPMODE=$APPMODE ENV APPENV=$APPENV +ENV STRIPE_PUBLIC_KEY=$STRIPE_PUBLIC_KEY # Copy the current directory into the Docker image COPY . /taas-app diff --git a/local/login-locally/README b/local/login-locally/README index a72052b8..080616cf 100644 --- a/local/login-locally/README +++ b/local/login-locally/README @@ -5,7 +5,3 @@ 3. Now you can open http://localhost:5000 in browser and click login (wait it a little bit, it may take time to redirect you). After you login, you should be redirected back to http://localhost:3000 PS. You may also download latest version of `setupAuth0WithRedirect.js` file from here - https://github.com/topcoder-platform/tc-auth-lib/blob/dev/web-assets/js/setupAuth0WithRedirect.js - - - - diff --git a/local/login-locally/index.html b/local/login-locally/index.html index 5217f1bc..3129ead1 100644 --- a/local/login-locally/index.html +++ b/local/login-locally/index.html @@ -1,18 +1,20 @@ - - + Auth0 - - + + - + Loaded...redirecting to auth0.(see browser console log) - Login - - + Login + diff --git a/local/login-locally/setupAuth0WithRedirect.js b/local/login-locally/setupAuth0WithRedirect.js index 8f6bdaf9..464a37e3 100644 --- a/local/login-locally/setupAuth0WithRedirect.js +++ b/local/login-locally/setupAuth0WithRedirect.js @@ -1,628 +1,677 @@ -var script = document.createElement('script'); -script.src = "https://cdn.auth0.com/js/auth0-spa-js/1.10/auth0-spa-js.production.js"; -script.type = 'text/javascript'; +var script = document.createElement("script"); +script.src = + "https://cdn.auth0.com/js/auth0-spa-js/1.10/auth0-spa-js.production.js"; +script.type = "text/javascript"; script.defer = true; -document.getElementsByTagName('head').item(0).appendChild(script); +document.getElementsByTagName("head").item(0).appendChild(script); -/** - * read query string - * +/** + * read query string + * */ const qs = (function (a) { - if (a == "") return {}; - let b = {}; - for (let i = 0; i < a.length; ++i) { - let p = a[i].split('=', 2); - if (p.length == 1) - b[p[0]] = ""; - else - b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); - } - return b; -})(window.location.search.substr(1).split('&')); + if (a == "") return {}; + let b = {}; + for (let i = 0; i < a.length; ++i) { + let p = a[i].split("=", 2); + if (p.length == 1) b[p[0]] = ""; + else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); + } + return b; +})(window.location.search.substr(1).split("&")); const authSetup = function () { - - let domain = 'auth.topcoder-dev.com'; - const clientId = 'BXWXUWnilVUPdN01t2Se29Tw2ZYNGZvH'; - const useLocalStorage = false; - const useRefreshTokens = false; - const v3JWTCookie = 'v3jwt'; - const tcJWTCookie = 'tcjwt'; - const tcSSOCookie = 'tcsso'; - const cookieExpireIn = 12 * 60; // 12 hrs - const refreshTokenInterval = 30000; // in milliseconds - const refreshTokenOffset = 65; // in seconds - const shouldLogout = qs['logout']; - const regSource = qs['regSource']; - const utmSource = qs['utm_source']; - const utmMedium = qs['utm_medium']; - const utmCampaign = qs['utm_campaign']; - const loggerMode = "dev"; - const IframeLogoutRequestType = "LOGOUT_REQUEST"; - const enterpriseCustomers = ['zurich', 'cs']; - const mode = qs['mode'] || 'signIn'; - let returnAppUrl = qs['retUrl']; - let appUrl = qs['appUrl'] || false; - - if (utmSource && - (utmSource != 'undefined') && - (enterpriseCustomers.indexOf(utmSource) > -1)) { - domain = "topcoder-dev.auth0.com"; - returnAppUrl += '&utm_source=' + utmSource; + let domain = "auth.topcoder-dev.com"; + const clientId = "BXWXUWnilVUPdN01t2Se29Tw2ZYNGZvH"; + const useLocalStorage = false; + const useRefreshTokens = false; + const v3JWTCookie = "v3jwt"; + const tcJWTCookie = "tcjwt"; + const tcSSOCookie = "tcsso"; + const cookieExpireIn = 12 * 60; // 12 hrs + const refreshTokenInterval = 30000; // in milliseconds + const refreshTokenOffset = 65; // in seconds + const shouldLogout = qs["logout"]; + const regSource = qs["regSource"]; + const utmSource = qs["utm_source"]; + const utmMedium = qs["utm_medium"]; + const utmCampaign = qs["utm_campaign"]; + const loggerMode = "dev"; + const IframeLogoutRequestType = "LOGOUT_REQUEST"; + const enterpriseCustomers = ["zurich", "cs"]; + const mode = qs["mode"] || "signIn"; + let returnAppUrl = qs["retUrl"]; + let appUrl = qs["appUrl"] || false; + + if ( + utmSource && + utmSource != "undefined" && + enterpriseCustomers.indexOf(utmSource) > -1 + ) { + domain = "topcoder-dev.auth0.com"; + returnAppUrl += "&utm_source=" + utmSource; + } + + var auth0 = null; + var isAuthenticated = false; + var idToken = null; + var callRefreshTokenFun = null; + var host = window.location.protocol + "//" + window.location.host; + const registerSuccessUrl = host + "/register_success.html"; + + const init = function () { + correctOldUrl(); + changeWindowMessage(); + createAuth0Client({ + domain: domain, + client_id: clientId, + cacheLocation: useLocalStorage ? "localstorage" : "memory", + useRefreshTokens: useRefreshTokens, + }) + .then(_init) + .catch(function (e) { + logger("Error occurred in initializing auth0 object: ", e); + window.location.reload(); + }); + window.addEventListener("message", receiveMessage, false); + }; + + const _init = function (authObj) { + auth0 = authObj; + if (qs["code"] && qs["state"]) { + auth0 + .handleRedirectCallback() + .then(function (data) { + logger("handleRedirectCallback() success: ", data); + showAuth0Info(); + storeToken(); + }) + .catch(function (e) { + logger("handleRedirectCallback() error: ", e); + }); + } else if (shouldLogout) { + host = returnAppUrl ? returnAppUrl : host; + logout(); + return; + } else if (!isLoggedIn() && returnAppUrl) { + login(); + } else if (qs["error"] && qs["state"]) { + logger("Error in executing callback(): ", qs["error_description"]); + showLoginError(qs["error_description"], appUrl); + } else { + logger("User already logged in", true); + postLogin(); } - - - var auth0 = null; - var isAuthenticated = false; - var idToken = null; - var callRefreshTokenFun = null; - var host = window.location.protocol + "//" + window.location.host - const registerSuccessUrl = host + '/register_success.html'; - - const init = function () { - correctOldUrl(); - changeWindowMessage(); - createAuth0Client({ + showAuthenticated(); + }; + + const showAuthenticated = function () { + auth0.isAuthenticated().then(function (isAuthenticated) { + isAuthenticated = isAuthenticated; + logger("_init:isAuthenticated", isAuthenticated); + }); + }; + + const refreshToken = function () { + let d = new Date(); + logger( + "checking token status at: ", + `${d.getHours()}::${d.getMinutes()}::${d.getSeconds()} ` + ); + var token = getCookie(v3JWTCookie); + if (!token || isTokenExpired(token)) { + logger( + "refreshing token... at: ", + `${d.getHours()}::${d.getMinutes()}::${d.getSeconds()} ` + ); + try { + let issuerHostname = ""; + if (token) { + let tokenJson = decodeToken(token); + let issuer = tokenJson.iss; + issuerHostname = extractHostname(issuer); + } + if (domain !== issuerHostname) { + domain = issuerHostname; + logger("reintialize auth0 for new domain..", domain); + createAuth0Client({ domain: domain, client_id: clientId, - cacheLocation: useLocalStorage - ? 'localstorage' - : 'memory', - useRefreshTokens: useRefreshTokens - }).then(_init).catch(function (e) { - logger("Error occurred in initializing auth0 object: ", e); - window.location.reload(); - }); - window.addEventListener("message", receiveMessage, false); - }; - - const _init = function (authObj) { - auth0 = authObj - if (qs['code'] && qs['state']) { - auth0.handleRedirectCallback().then(function (data) { - logger('handleRedirectCallback() success: ', data); + cacheLocation: useLocalStorage ? "localstorage" : "memory", + useRefreshTokens: useRefreshTokens, + }).then(function (newAuth0Obj) { + auth0 = newAuth0Obj; + auth0 + .getTokenSilently() + .then(function (token) { showAuth0Info(); storeToken(); - }).catch(function (e) { - logger('handleRedirectCallback() error: ', e); - }); - } else if (shouldLogout) { - host = returnAppUrl ? returnAppUrl : host; - logout(); - return; - } else if (!isLoggedIn() && returnAppUrl) { - login(); - } else if (qs['error'] && qs['state']) { - logger("Error in executing callback(): ", qs['error_description']); - showLoginError(qs['error_description'], appUrl); - } else { - logger("User already logged in", true); - postLogin(); - } - showAuthenticated(); - }; - - const showAuthenticated = function () { - auth0.isAuthenticated().then(function (isAuthenticated) { - isAuthenticated = isAuthenticated; - logger("_init:isAuthenticated", isAuthenticated); - }); - }; - - const refreshToken = function () { - let d = new Date(); - logger('checking token status at: ', `${d.getHours()}::${d.getMinutes()}::${d.getSeconds()} `); - var token = getCookie(v3JWTCookie); - if (!token || isTokenExpired(token)) { - logger('refreshing token... at: ', `${d.getHours()}::${d.getMinutes()}::${d.getSeconds()} `); - try { - let issuerHostname = ""; - if (token) { - let tokenJson = decodeToken(token); - let issuer = tokenJson.iss; - issuerHostname = extractHostname(issuer); + logger("refreshing token for new domain..", domain); + }) + .catch(function (e) { + logger("Error in refreshing token: ", e); + if ( + e.error && + (e.error == "login_required" || e.error == "timeout") + ) { + clearInterval(callRefreshTokenFun); + clearAllCookies(); } - if (domain !== issuerHostname) { - domain = issuerHostname; - logger("reintialize auth0 for new domain..", domain); - createAuth0Client({ - domain: domain, - client_id: clientId, - cacheLocation: useLocalStorage - ? 'localstorage' - : 'memory', - useRefreshTokens: useRefreshTokens - }).then(function (newAuth0Obj) { - auth0 = newAuth0Obj; - auth0.getTokenSilently().then(function (token) { - showAuth0Info(); - storeToken(); - logger("refreshing token for new domain..", domain); - }).catch(function (e) { - logger("Error in refreshing token: ", e) - if (e.error && ((e.error == "login_required") || (e.error == "timeout"))) { - clearInterval(callRefreshTokenFun); - clearAllCookies(); - } - } - ); - }); - } else { - auth0.getTokenSilently().then(function (token) { - showAuth0Info(); - storeToken(); - }).catch(function (e) { - logger("Error in refreshing token: ", e) - if (e.error && ((e.error == "login_required") || (e.error == "timeout"))) { - clearInterval(callRefreshTokenFun); - clearAllCookies(); - } - } - ); - } - } catch (e) { - logger("Error in refresh token function ", e.message) - } - - } - }; - - const showAuth0Info = function () { - auth0.getUser().then(function (user) { - logger("User Profile: ", user); - }); - auth0.getIdTokenClaims().then(function (claims) { - idToken = claims.__raw; - logger("JWT Token: ", idToken); - }); - }; - - const login = function () { - auth0 - .loginWithRedirect({ - redirect_uri: host + '?appUrl=' + returnAppUrl, - regSource: regSource, - utmSource: utmSource, - utmCampaign: utmCampaign, - utmMedium: utmMedium, - returnUrl: returnAppUrl, - mode: mode + }); + }); + } else { + auth0 + .getTokenSilently() + .then(function (token) { + showAuth0Info(); + storeToken(); }) - .then(function () { - auth0.isAuthenticated().then(function (isAuthenticated) { - isAuthenticated = isAuthenticated; - if (isAuthenticated) { - showAuth0Info(); - storeToken(); - postLogin(); - } - }); + .catch(function (e) { + logger("Error in refreshing token: ", e); + if ( + e.error && + (e.error == "login_required" || e.error == "timeout") + ) { + clearInterval(callRefreshTokenFun); + clearAllCookies(); + } }); - }; - - const logout = function () { - clearAllCookies(); - auth0.logout({ - returnTo: host + } + } catch (e) { + logger("Error in refresh token function ", e.message); + } + } + }; + + const showAuth0Info = function () { + auth0.getUser().then(function (user) { + logger("User Profile: ", user); + }); + auth0.getIdTokenClaims().then(function (claims) { + idToken = claims.__raw; + logger("JWT Token: ", idToken); + }); + }; + + const login = function () { + auth0 + .loginWithRedirect({ + redirect_uri: host + "?appUrl=" + returnAppUrl, + regSource: regSource, + utmSource: utmSource, + utmCampaign: utmCampaign, + utmMedium: utmMedium, + returnUrl: returnAppUrl, + mode: mode, + }) + .then(function () { + auth0.isAuthenticated().then(function (isAuthenticated) { + isAuthenticated = isAuthenticated; + if (isAuthenticated) { + showAuth0Info(); + storeToken(); + postLogin(); + } }); - }; - - const clearAllCookies = function () { - // TODO - setCookie(tcJWTCookie, "", -1); - setCookie(v3JWTCookie, "", -1); - setCookie(tcSSOCookie, "", -1); - - // to clear any old session - setCookie('auth0Jwt', "", -1); - setCookie('zendeskJwt', "", -1); - setCookie('auth0Refresh', "", -1); - // for scorecard - setCookie('JSESSIONID', "", -1); + }); + }; + + const logout = function () { + clearAllCookies(); + auth0.logout({ + returnTo: host, + }); + }; + + const clearAllCookies = function () { + // TODO + setCookie(tcJWTCookie, "", -1); + setCookie(v3JWTCookie, "", -1); + setCookie(tcSSOCookie, "", -1); + + // to clear any old session + setCookie("auth0Jwt", "", -1); + setCookie("zendeskJwt", "", -1); + setCookie("auth0Refresh", "", -1); + // for scorecard + setCookie("JSESSIONID", "", -1); + }; + + const isLoggedIn = function () { + var token = getCookie(v3JWTCookie); + return token ? !isTokenExpired(token) : false; + }; + + const redirectToApp = function () { + logger("redirect to app", appUrl); + if (appUrl) { + window.location = appUrl; } + }; - const isLoggedIn = function () { - var token = getCookie(v3JWTCookie); - return token ? !isTokenExpired(token) : false; - }; - - const redirectToApp = function () { - logger("redirect to app", appUrl); - if (appUrl) { - window.location = appUrl; - } - }; - - const postLogin = function () { - if (isLoggedIn() && returnAppUrl) { - auth0.isAuthenticated().then(function (isAuthenticated) { - if (isAuthenticated) { - window.location = returnAppUrl; - } else { - login(); // old session exist case - } - }); - } - logger('calling postLogin: ', true); - logger('callRefreshTokenFun: ', callRefreshTokenFun); - if (callRefreshTokenFun != null) { - clearInterval(callRefreshTokenFun); + const postLogin = function () { + if (isLoggedIn() && returnAppUrl) { + auth0.isAuthenticated().then(function (isAuthenticated) { + if (isAuthenticated) { + window.location = returnAppUrl; + } else { + login(); // old session exist case } - refreshToken(); - callRefreshTokenFun = setInterval(refreshToken, refreshTokenInterval); + }); } - - const storeToken = function () { - auth0.getIdTokenClaims().then(function (claims) { - idToken = claims.__raw; - let userActive = false; - Object.keys(claims).findIndex(function (key) { - if (key.includes('active')) { - userActive = claims[key]; - return true; - } - return false; - }); - if (userActive) { - let tcsso = ''; - Object.keys(claims).findIndex(function (key) { - if (key.includes(tcSSOCookie)) { - tcsso = claims[key]; - return true; - } - return false; - }); - logger('Storing token...', true); - try { - const exT = getCookieExpiry(idToken); - if (exT) { - setDomainCookie(tcJWTCookie, idToken, exT); - setDomainCookie(v3JWTCookie, idToken, exT); - setDomainCookie(tcSSOCookie, tcsso, exT); - } else { - setCookie(tcJWTCookie, idToken, cookieExpireIn); - setCookie(v3JWTCookie, idToken, cookieExpireIn); - setCookie(tcSSOCookie, tcsso, cookieExpireIn); - } - } catch (e) { - logger('Error occured in fecthing token expiry time', e.message); - } - - // session still active, but app calling login - if (!appUrl && returnAppUrl) { - appUrl = returnAppUrl - } - redirectToApp(); + logger("calling postLogin: ", true); + logger("callRefreshTokenFun: ", callRefreshTokenFun); + if (callRefreshTokenFun != null) { + clearInterval(callRefreshTokenFun); + } + refreshToken(); + callRefreshTokenFun = setInterval(refreshToken, refreshTokenInterval); + }; + + const storeToken = function () { + auth0 + .getIdTokenClaims() + .then(function (claims) { + idToken = claims.__raw; + let userActive = false; + Object.keys(claims).findIndex(function (key) { + if (key.includes("active")) { + userActive = claims[key]; + return true; + } + return false; + }); + if (userActive) { + let tcsso = ""; + Object.keys(claims).findIndex(function (key) { + if (key.includes(tcSSOCookie)) { + tcsso = claims[key]; + return true; + } + return false; + }); + logger("Storing token...", true); + try { + const exT = getCookieExpiry(idToken); + if (exT) { + setDomainCookie(tcJWTCookie, idToken, exT); + setDomainCookie(v3JWTCookie, idToken, exT); + setDomainCookie(tcSSOCookie, tcsso, exT); } else { - logger("User active ? ", userActive); - host = registerSuccessUrl; - logout(); + setCookie(tcJWTCookie, idToken, cookieExpireIn); + setCookie(v3JWTCookie, idToken, cookieExpireIn); + setCookie(tcSSOCookie, tcsso, cookieExpireIn); } - }).catch(function (e) { - logger("Error in fetching token from auth0: ", e); - }); - }; - - /////// Token.js - - function getTokenExpirationDate(token) { - const decoded = decodeToken(token); - if (typeof decoded.exp === 'undefined') { - return null; + } catch (e) { + logger("Error occured in fecthing token expiry time", e.message); + } + + // session still active, but app calling login + if (!appUrl && returnAppUrl) { + appUrl = returnAppUrl; + } + redirectToApp(); + } else { + logger("User active ? ", userActive); + host = registerSuccessUrl; + logout(); } - const d = new Date(0); // The 0 here is the key, which sets the date to the epoch - d.setUTCSeconds(decoded.exp); - return d; + }) + .catch(function (e) { + logger("Error in fetching token from auth0: ", e); + }); + }; + + /////// Token.js + + function getTokenExpirationDate(token) { + const decoded = decodeToken(token); + if (typeof decoded.exp === "undefined") { + return null; } + const d = new Date(0); // The 0 here is the key, which sets the date to the epoch + d.setUTCSeconds(decoded.exp); + return d; + } - function decodeToken(token) { - const parts = token.split('.'); - - if (parts.length !== 3) { - throw new Error('The token is invalid'); - } + function decodeToken(token) { + const parts = token.split("."); - const decoded = urlBase64Decode(parts[1]) + if (parts.length !== 3) { + throw new Error("The token is invalid"); + } - if (!decoded) { - throw new Error('Cannot decode the token'); - } + const decoded = urlBase64Decode(parts[1]); - // covert base64 token in JSON object - let t = JSON.parse(decoded); - return t; + if (!decoded) { + throw new Error("Cannot decode the token"); } - function isTokenExpired(token, offsetSeconds = refreshTokenOffset) { - const d = getTokenExpirationDate(token) + // covert base64 token in JSON object + let t = JSON.parse(decoded); + return t; + } - if (d === null) { - return false; - } + function isTokenExpired(token, offsetSeconds = refreshTokenOffset) { + const d = getTokenExpirationDate(token); - // Token expired? - return !(d.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000))); + if (d === null) { + return false; } - function urlBase64Decode(str) { - let output = str.replace(/-/g, '+').replace(/_/g, '/') + // Token expired? + return !(d.valueOf() > new Date().valueOf() + offsetSeconds * 1000); + } - switch (output.length % 4) { - case 0: - break; + function urlBase64Decode(str) { + let output = str.replace(/-/g, "+").replace(/_/g, "/"); - case 2: - output += '==' - break; - - case 3: - output += '=' - break; - - default: - throw 'Illegal base64url string!'; - } - return decodeURIComponent(escape(atob(output))); //polyfill https://github.com/davidchambers/Base64.js - } + switch (output.length % 4) { + case 0: + break; - function setCookie(cname, cvalue, exMins) { - const cdomain = getHostDomain(); + case 2: + output += "=="; + break; - let d = new Date(); - d.setTime(d.getTime() + (exMins * 60 * 1000)); + case 3: + output += "="; + break; - let expires = ";expires=" + d.toUTCString(); - document.cookie = cname + "=" + cvalue + cdomain + expires + ";path=/"; + default: + throw "Illegal base64url string!"; } - - function getCookie(name) { - const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); - return v ? v[2] : undefined; + return decodeURIComponent(escape(atob(output))); //polyfill https://github.com/davidchambers/Base64.js + } + + function setCookie(cname, cvalue, exMins) { + const cdomain = getHostDomain(); + + let d = new Date(); + d.setTime(d.getTime() + exMins * 60 * 1000); + + let expires = ";expires=" + d.toUTCString(); + document.cookie = cname + "=" + cvalue + cdomain + expires + ";path=/"; + } + + function getCookie(name) { + const v = document.cookie.match("(^|;) ?" + name + "=([^;]*)(;|$)"); + return v ? v[2] : undefined; + } + // end token.js + + function getHostDomain() { + let hostDomain = ""; + if (location.hostname !== "localhost") { + hostDomain = + ";domain=." + + location.hostname.split(".").reverse()[1] + + "." + + location.hostname.split(".").reverse()[0]; } - // end token.js - - function getHostDomain() { - let hostDomain = ""; - if (location.hostname !== 'localhost') { - hostDomain = ";domain=." + - location.hostname.split('.').reverse()[1] + - "." + location.hostname.split('.').reverse()[0]; - } - return hostDomain; + return hostDomain; + } + + function correctOldUrl() { + const pattern = "#!/member"; + const sso_pattern = "/#!/sso-login"; + const logout_pattern = "/#!/logout?"; + + const url = window.location.href; + + const result = url.match(/^(.+)(\#!\/(.+)\?)(.+)/); + + if (result) { + try { + const newUrl = result[1] + "?" + result[4]; + logger("new url: ", newUrl); + window.location.href = newUrl; + } catch (e) { + logger("Creating new url error: ", e.message); + } + } + // Need to cleanup below code, should never execute + if (window.location.href.indexOf(pattern) > -1) { + window.location.href = window.location.href.replace(pattern, ""); } - function correctOldUrl() { - const pattern = '#!/member'; - const sso_pattern = '/#!/sso-login'; - const logout_pattern = '/#!/logout?'; - - const url = window.location.href; - - const result = url.match(/^(.+)(\#!\/(.+)\?)(.+)/); - - if (result) { - try { - const newUrl = result[1] + "?" + result[4]; - logger("new url: ", newUrl); - window.location.href = newUrl; - } catch (e) { - logger("Creating new url error: ", e.message); - } - } - // Need to cleanup below code, should never execute - if (window.location.href.indexOf(pattern) > -1) { - window.location.href = window.location.href.replace(pattern, ''); - } - - if (window.location.href.indexOf(sso_pattern) > -1) { - window.location.href = window.location.href.replace(sso_pattern, ''); - } - - if (window.location.href.indexOf(logout_pattern) > -1) { - window.location.href = window.location.href.replace(logout_pattern, '/?logout=true&'); - } + if (window.location.href.indexOf(sso_pattern) > -1) { + window.location.href = window.location.href.replace(sso_pattern, ""); } - function logger(label, message) { - if (loggerMode === "dev") { - console.log(label, message); - } + if (window.location.href.indexOf(logout_pattern) > -1) { + window.location.href = window.location.href.replace( + logout_pattern, + "/?logout=true&" + ); } + } - /** - * will receive message from iframe - */ - function receiveMessage(e) { - logger("received Event:", e); - if (e.data && e.data.type && e.origin) { - if (e.data.type === IframeLogoutRequestType) { - host = e.origin; - logout(); - } - } - if (e.data && e.data.type && e.data.type === "REFRESH_TOKEN") { - const token = getCookie(v3JWTCookie); - const failed = { - type: "FAILURE" - }; - const success = { - type: "SUCCESS" - }; - - const informIt = function (payload) { - e.source.postMessage(payload, e.origin); - } - try { - const storeRefreshedToken = function (aObj) { - aObj.getIdTokenClaims().then(function (claims) { - idToken = claims.__raw; - let userActive = false; - Object.keys(claims).findIndex(function (key) { - if (key.includes('active')) { - userActive = claims[key]; - return true; - } - return false; - }); - if (userActive) { - let tcsso = ''; - Object.keys(claims).findIndex(function (key) { - if (key.includes(tcSSOCookie)) { - tcsso = claims[key]; - return true; - } - return false; - }); - logger('Storing refreshed token...', true); - try { - const exT = getCookieExpiry(idToken); - if (exT) { - setDomainCookie(tcJWTCookie, idToken, exT); - setDomainCookie(v3JWTCookie, idToken, exT); - setDomainCookie(tcSSOCookie, tcsso, exT); - } else { - setCookie(tcJWTCookie, idToken, cookieExpireIn); - setCookie(v3JWTCookie, idToken, cookieExpireIn); - setCookie(tcSSOCookie, tcsso, cookieExpireIn); - } - informIt(success); - } catch (e) { - logger('Error occured in fecthing token expiry time', e.message); - informIt(failed); - } - } else { - logger("Refeshed token - user active ? ", userActive); - informIt(failed); - } - }).catch(function (err) { - logger("Refeshed token - error in fetching token from auth0: ", err); - informIt(failed); - }); - }; - - const getToken = function (aObj) { - aObj.getTokenSilently({ timeoutInSeconds: 60 }).then(function (token) { - storeRefreshedToken(aObj); - }).catch(function (err) { - logger("receiveMessage: Error in refreshing token through iframe:", err) - informIt(failed); - }); - - }; - - // main execution start here - if (token && !isTokenExpired(token)) { - informIt(success); - } else if (!token) { - const auth0Session = getCookie('auth0.is.authenticated'); - logger('auth0 session available ?', auth0Session); - if (auth0Session) { - logger('auth session true', 1); - if (!auth0) { - createAuth0Client({ - domain: domain, - client_id: clientId, - cacheLocation: useLocalStorage - ? 'localstorage' - : 'memory', - useRefreshTokens: useRefreshTokens - }).then(function (newAuth0Obj) { - getToken(newAuth0Obj); - }).catch(function (e) { - logger("Error occurred in re-initializing auth0 object: ", e); - informIt(failed); - }); - } else { - getToken(auth0); - } - } else { - informIt(failed); - } - - } else { - if (auth0) { - getToken(auth0); - } else { - informIt(failed); - } + function logger(label, message) { + if (loggerMode === "dev") { + console.log(label, message); + } + } + + /** + * will receive message from iframe + */ + function receiveMessage(e) { + logger("received Event:", e); + if (e.data && e.data.type && e.origin) { + if (e.data.type === IframeLogoutRequestType) { + host = e.origin; + logout(); + } + } + if (e.data && e.data.type && e.data.type === "REFRESH_TOKEN") { + const token = getCookie(v3JWTCookie); + const failed = { + type: "FAILURE", + }; + const success = { + type: "SUCCESS", + }; + + const informIt = function (payload) { + e.source.postMessage(payload, e.origin); + }; + try { + const storeRefreshedToken = function (aObj) { + aObj + .getIdTokenClaims() + .then(function (claims) { + idToken = claims.__raw; + let userActive = false; + Object.keys(claims).findIndex(function (key) { + if (key.includes("active")) { + userActive = claims[key]; + return true; + } + return false; + }); + if (userActive) { + let tcsso = ""; + Object.keys(claims).findIndex(function (key) { + if (key.includes(tcSSOCookie)) { + tcsso = claims[key]; + return true; + } + return false; + }); + logger("Storing refreshed token...", true); + try { + const exT = getCookieExpiry(idToken); + if (exT) { + setDomainCookie(tcJWTCookie, idToken, exT); + setDomainCookie(v3JWTCookie, idToken, exT); + setDomainCookie(tcSSOCookie, tcsso, exT); + } else { + setCookie(tcJWTCookie, idToken, cookieExpireIn); + setCookie(v3JWTCookie, idToken, cookieExpireIn); + setCookie(tcSSOCookie, tcsso, cookieExpireIn); + } + informIt(success); + } catch (e) { + logger( + "Error occured in fecthing token expiry time", + e.message + ); + informIt(failed); } - } catch (e) { - logger("error occured in iframe handler:", e.message); + } else { + logger("Refeshed token - user active ? ", userActive); informIt(failed); + } + }) + .catch(function (err) { + logger( + "Refeshed token - error in fetching token from auth0: ", + err + ); + informIt(failed); + }); + }; + + const getToken = function (aObj) { + aObj + .getTokenSilently({ timeoutInSeconds: 60 }) + .then(function (token) { + storeRefreshedToken(aObj); + }) + .catch(function (err) { + logger( + "receiveMessage: Error in refreshing token through iframe:", + err + ); + informIt(failed); + }); + }; + + // main execution start here + if (token && !isTokenExpired(token)) { + informIt(success); + } else if (!token) { + const auth0Session = getCookie("auth0.is.authenticated"); + logger("auth0 session available ?", auth0Session); + if (auth0Session) { + logger("auth session true", 1); + if (!auth0) { + createAuth0Client({ + domain: domain, + client_id: clientId, + cacheLocation: useLocalStorage ? "localstorage" : "memory", + useRefreshTokens: useRefreshTokens, + }) + .then(function (newAuth0Obj) { + getToken(newAuth0Obj); + }) + .catch(function (e) { + logger("Error occurred in re-initializing auth0 object: ", e); + informIt(failed); + }); + } else { + getToken(auth0); } + } else { + informIt(failed); + } } else { - // do nothing + if (auth0) { + getToken(auth0); + } else { + informIt(failed); + } } + } catch (e) { + logger("error occured in iframe handler:", e.message); + informIt(failed); + } + } else { + // do nothing } - - function changeWindowMessage() { - - if ((!returnAppUrl && !appUrl) || ((returnAppUrl == 'undefined') && (appUrl == 'undefined'))) { - try { - var hdomain = location.hostname.split('.').reverse()[1]; - var linkurl = "http://" + window.location.host + "/?logout=true&retUrl=http://" + window.location.host; - if (hdomain) { - linkurl = "https://" + window.location.host + "/?logout=true&retUrl=https://" + hdomain + ".com"; - } - document.getElementById("page-title-heading").innerHTML = "Alert"; - document.getElementById("loading_message_p").innerHTML = "Login/Logout action is not called. Please check return url (retUrl) value in query parameters or click here"; - } catch (err) { - logger("Error in changing loading message: ", err.message) - } + } + + function changeWindowMessage() { + if ( + (!returnAppUrl && !appUrl) || + (returnAppUrl == "undefined" && appUrl == "undefined") + ) { + try { + var hdomain = location.hostname.split(".").reverse()[1]; + var linkurl = + "http://" + + window.location.host + + "/?logout=true&retUrl=http://" + + window.location.host; + if (hdomain) { + linkurl = + "https://" + + window.location.host + + "/?logout=true&retUrl=https://" + + hdomain + + ".com"; } + document.getElementById("page-title-heading").innerHTML = "Alert"; + document.getElementById("loading_message_p").innerHTML = + "Login/Logout action is not called. Please check return url (retUrl) value in query parameters or click here"; + } catch (err) { + logger("Error in changing loading message: ", err.message); + } } + } - function extractHostname(url) { - var hostname; - //find & remove protocol (http, ftp, etc.) and get hostname + function extractHostname(url) { + var hostname; + //find & remove protocol (http, ftp, etc.) and get hostname - if (url.indexOf("//") > -1) { - hostname = url.split('/')[2]; - } - else { - hostname = url.split('/')[0]; - } - //find & remove port number - hostname = hostname.split(':')[0]; - //find & remove "?" - hostname = hostname.split('?')[0]; - - return hostname; + if (url.indexOf("//") > -1) { + hostname = url.split("/")[2]; + } else { + hostname = url.split("/")[0]; } - - function showLoginError(message, linkUrl) { - try { - document.getElementById("page-title-heading").innerHTML = "Alert"; - document.getElementById("loading_message_p").innerHTML = message + " click here"; - } catch (err) { - logger("Error in changing loading message: ", err.message) - } + //find & remove port number + hostname = hostname.split(":")[0]; + //find & remove "?" + hostname = hostname.split("?")[0]; + + return hostname; + } + + function showLoginError(message, linkUrl) { + try { + document.getElementById("page-title-heading").innerHTML = "Alert"; + document.getElementById("loading_message_p").innerHTML = + message + " click here"; + } catch (err) { + logger("Error in changing loading message: ", err.message); } + } - function getCookieExpiry(token) { - const d = getTokenExpirationDate(token) - if (d === null) { - return false; - } - const diff = d.valueOf() - (new Date().valueOf()); //in millseconds - if (diff > 0) { - return diff; // in milliseconds - } - return false; + function getCookieExpiry(token) { + const d = getTokenExpirationDate(token); + if (d === null) { + return false; } + const diff = d.valueOf() - new Date().valueOf(); //in millseconds + if (diff > 0) { + return diff; // in milliseconds + } + return false; + } - function setDomainCookie(cname, cvalue, exMilliSeconds) { - const cdomain = getHostDomain(); - - let d = new Date(); - d.setTime(d.getTime() + exMilliSeconds); + function setDomainCookie(cname, cvalue, exMilliSeconds) { + const cdomain = getHostDomain(); - let expires = ";expires=" + d.toUTCString(); - document.cookie = cname + "=" + cvalue + cdomain + expires + ";path=/"; - } + let d = new Date(); + d.setTime(d.getTime() + exMilliSeconds); + let expires = ";expires=" + d.toUTCString(); + document.cookie = cname + "=" + cvalue + cdomain + expires + ";path=/"; + } - // execute - init(); + // execute + init(); }; diff --git a/package-lock.json b/package-lock.json index b524184a..d0d5c0df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2695,6 +2695,115 @@ } } }, + "@material-ui/core": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", + "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.4", + "@material-ui/system": "^4.12.1", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "dependencies": { + "popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + } + } + }, + "@material-ui/icons": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", + "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, + "@material-ui/lab": { + "version": "4.0.0-alpha.60", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz", + "integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.2", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + } + }, + "@material-ui/styles": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", + "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==", + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "dependencies": { + "csstype": { + "version": "2.6.17", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", + "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + } + } + }, + "@material-ui/system": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz", + "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.2", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "dependencies": { + "csstype": { + "version": "2.6.17", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", + "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + } + } + }, + "@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==" + }, + "@material-ui/utils": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz", + "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + } + }, "@popperjs/core": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz", @@ -2726,6 +2835,19 @@ "type-detect": "4.0.8" } }, + "@stripe/react-stripe-js": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.4.1.tgz", + "integrity": "sha512-FjcVrhf72+9fUL3Lz3xi02ni9tzH1A1x6elXlr6tvBDgSD55oPJuodoP8eC7xTnBIKq0olF5uJvgtkJyDCdzjA==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "@stripe/stripe-js": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.16.0.tgz", + "integrity": "sha512-ZSHbiwTrISoaTbpercmYGuY7QTg7HxfFyNgbJBaYbwHWbzMhpEdGTsmMpaBXIU6iiqwEEDaIyD8O6yJ+H5DWCg==" + }, "@testing-library/dom": { "version": "6.16.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.16.0.tgz", @@ -2985,14 +3107,12 @@ "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", - "dev": true + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { "version": "16.9.51", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.51.tgz", "integrity": "sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ==", - "dev": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3007,6 +3127,14 @@ "@types/react": "*" } }, + "@types/react-transition-group": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ==", + "requires": { + "@types/react": "*" + } + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -4966,6 +5094,11 @@ "wrap-ansi": "^5.1.0" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5709,6 +5842,15 @@ } } }, + "css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "requires": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, "css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -8576,6 +8718,11 @@ "is-extglob": "^2.1.1" } }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -11982,6 +12129,84 @@ "verror": "1.10.0" } }, + "jss": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.7.1.tgz", + "integrity": "sha512-5QN8JSVZR6cxpZNeGfzIjqPEP+ZJwJJfZbXmeABNdxiExyO+eJJDy6WDtqTf8SDKnbL5kZllEpAP71E/Lt7PXg==", + "requires": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-camel-case": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.7.1.tgz", + "integrity": "sha512-+ioIyWvmAfgDCWXsQcW1NMnLBvRinOVFkSYJUgewQ6TynOcSj5F1bSU23B7z0p1iqK0PPHIU62xY1iNJD33WGA==", + "requires": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.7.1" + } + }, + "jss-plugin-default-unit": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.7.1.tgz", + "integrity": "sha512-tW+dfYVNARBQb/ONzBwd8uyImigyzMiAEDai+AbH5rcHg5h3TtqhAkxx06iuZiT/dZUiFdSKlbe3q9jZGAPIwA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-global": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.7.1.tgz", + "integrity": "sha512-FbxCnu44IkK/bw8X3CwZKmcAnJqjAb9LujlAc/aP0bMSdVa3/MugKQRyeQSu00uGL44feJJDoeXXiHOakBr/Zw==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-nested": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.7.1.tgz", + "integrity": "sha512-RNbICk7FlYKaJyv9tkMl7s6FFfeLA3ubNIFKvPqaWtADK0KUaPsPXVYBkAu4x1ItgsWx67xvReMrkcKA0jSXfA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.7.1.tgz", + "integrity": "sha512-eyd5FhA+J0QrpqXxO7YNF/HMSXXl4pB0EmUdY4vSJI4QG22F59vQ6AHtP6fSwhmBdQ98Qd9gjfO+RMxcE39P1A==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.7.1.tgz", + "integrity": "sha512-fGAAImlbaHD3fXAHI3ooX6aRESOl5iBt3LjpVjxs9II5u9tzam7pqFUmgTcrip9VpRqYHn8J3gA7kCtm8xKwHg==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.7.1.tgz", + "integrity": "sha512-1UHFmBn7hZNsHXTkLLOL8abRl8vi+D1EVzWD4WmLFj55vawHZfnH1oEz6TUf5Y61XHv0smdHabdXds6BgOXe3A==", + "requires": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.7.1" + } + }, "jsx-ast-utils": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", @@ -16666,6 +16891,11 @@ "setimmediate": "^1.0.4" } }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index a95fce45..7765e741 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,13 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "@material-ui/core": "^4.12.3", + "@material-ui/icons": "^4.11.2", + "@material-ui/lab": "^4.0.0-alpha.60", "@popperjs/core": "^2.5.4", "@reach/router": "^1.3.4", + "@stripe/react-stripe-js": "^1.4.1", + "@stripe/stripe-js": "^1.16.0", "@toast-ui/editor": "^2.5.1", "axios": "^0.21.0", "classnames": "^2.2.6", diff --git a/src/assets/images/customer-logos.svg b/src/assets/images/customer-logos.svg index 0719e61e..6748a16c 100644 --- a/src/assets/images/customer-logos.svg +++ b/src/assets/images/customer-logos.svg @@ -1,139 +1,192 @@ - - - Homepage-Logos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + diff --git a/src/components/Accordion/styles.module.scss b/src/components/Accordion/styles.module.scss index ffa9a997..4ff714ef 100644 --- a/src/components/Accordion/styles.module.scss +++ b/src/components/Accordion/styles.module.scss @@ -27,23 +27,23 @@ .down-arrow { display: inline-block; - content: ''; + content: ""; height: 13px; width: 13px; margin-right: 16px; - border-bottom: 3px solid #137D60; - border-right: 3px solid #137D60; + border-bottom: 3px solid #137d60; + border-right: 3px solid #137d60; transform: rotate(45deg); } .right-arrow { display: inline-block; - content: ''; + content: ""; height: 13px; width: 13px; margin-right: 16px; - border-bottom: 3px solid #137D60; - border-right: 3px solid #137D60; + border-bottom: 3px solid #137d60; + border-right: 3px solid #137d60; transform: rotate(-45deg); } @@ -67,4 +67,4 @@ .panel { padding-left: 28px; font-size: 14px; -} \ No newline at end of file +} diff --git a/src/components/ActionsMenu/styles.module.scss b/src/components/ActionsMenu/styles.module.scss index 18d15c78..d1c6fdb0 100644 --- a/src/components/ActionsMenu/styles.module.scss +++ b/src/components/ActionsMenu/styles.module.scss @@ -51,7 +51,7 @@ } .danger { - color: #EF476F; + color: #ef476f; } .disabled { diff --git a/src/components/AsyncSelect/index.jsx b/src/components/AsyncSelect/index.jsx index 269ad803..bb3cd3c2 100644 --- a/src/components/AsyncSelect/index.jsx +++ b/src/components/AsyncSelect/index.jsx @@ -87,8 +87,8 @@ const AsyncSelect = (props) => { defaultOptions={props.defaultOptions} /> - ) -} + ); +}; AsyncSelect.propTypes = { value: PT.string, @@ -106,6 +106,6 @@ AsyncSelect.propTypes = { loadOptions: PT.func, defaultOptions: PT.bool || PT.array, disabled: PT.bool, -} +}; -export default AsyncSelect; \ No newline at end of file +export default AsyncSelect; diff --git a/src/components/Checkbox/index.jsx b/src/components/Checkbox/index.jsx index b4cbb52d..0431fa0f 100644 --- a/src/components/Checkbox/index.jsx +++ b/src/components/Checkbox/index.jsx @@ -1,19 +1,27 @@ import React from "react"; import PT from "prop-types"; +import cn from "classnames"; import "./styles.module.scss"; -function Checkbox({ label, checked, onClick }) { +function Checkbox({ label, disabled, checkmarkFloat, checked, onClick }) { return ( -