From 2229ba931b6eadafc0c999d306fce9e6e3dc7339 Mon Sep 17 00:00:00 2001
From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com>
Date: Tue, 16 Feb 2021 23:29:24 +0300
Subject: Adds Error Handler For OAuth Button

Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com>
---
 src/components/OAuth2Button.tsx | 64 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 11 deletions(-)

(limited to 'src/components/OAuth2Button.tsx')

diff --git a/src/components/OAuth2Button.tsx b/src/components/OAuth2Button.tsx
index 90a25fa..61bcd99 100644
--- a/src/components/OAuth2Button.tsx
+++ b/src/components/OAuth2Button.tsx
@@ -1,11 +1,12 @@
 /** @jsx jsx */
 import { css, jsx } from "@emotion/react";
-import { useState } from "react";
+import React, { useState } from "react";
 
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faDiscord } from "@fortawesome/free-brands-svg-icons";
 
-import authenticate, {checkScopes, OAuthScopes} from "../api/auth";
+import authenticate, { APIErrors, checkScopes, OAuthScopes } from "../api/auth";
+import { selectable } from "../commonStyles";
 
 
 interface OAuth2ButtonProps {
@@ -26,22 +27,63 @@ const textStyles = css`
   padding: 0.5rem 0.75rem 0.5rem 0.5rem;
 `;
 
-function OAuth2Button(props: OAuth2ButtonProps): JSX.Element {
-    const [disabled, setDisabled] = useState<boolean>(false);
-    async function login() {
-        await authenticate(props.scopes, setDisabled, props.path);
+const errorStyles =  css`
+  position: absolute;
+  visibility: hidden;
+  width: 100%;
+  left: 0;
+  
+  text-align: center;
+  white-space: normal;
+  box-sizing: border-box;
+  padding: 0 5rem;
+  
+  color: red;
+  margin-top: 2.5rem;
+`;
+
+async function login(props: OAuth2ButtonProps, errorDialog: React.RefObject<HTMLDivElement>, setDisabled: (newState: boolean) => void) {
+    await authenticate(props.scopes, setDisabled, props.path).catch((reason: APIErrors) => {
+        // Display Error Message
+        if (errorDialog.current) {
+            errorDialog.current.style.visibility = "visible";
+            errorDialog.current.textContent = reason.Message;
+            errorDialog.current.scrollIntoView({behavior: "smooth"});
+        }
+
+        // Propagate to sentry
+        const error = reason.Error.toJSON();
+        error["Custom Error Message"] = reason.Message;
+
+        // Filter Discord code
+        if (error?.config?.data) {
+            const data = JSON.parse(error.config.data);
+            if (data["token"]) {
+                data["token"] = "[FILTERED]";
+            }
 
-        if (checkScopes(props.scopes, props.path)) {
-            props.rerender();
+            error.config.data = data;
         }
+
+        throw error;
+    });
+
+    if (checkScopes(props.scopes, props.path)) {
+        props.rerender();
     }
+}
+
+function OAuth2Button(props: OAuth2ButtonProps): JSX.Element {
+    const [disabled, setDisabled] = useState<boolean>(false);
+    const errorDialog: React.RefObject<HTMLDivElement> = React.useRef(null);
 
-    return (
-        <button disabled={disabled} onClick={() => login()}>
+    return <span>
+        <button disabled={disabled} onClick={() => login(props, errorDialog, setDisabled)}>
             <FontAwesomeIcon icon={faDiscord} css={iconStyles}/>
             <span css={textStyles}>Discord Login</span>
         </button>
-    );
+        <div css={[errorStyles, selectable]} ref={errorDialog}/>
+    </span>;
 }
 
 export default OAuth2Button;
-- 
cgit v1.2.3

