diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json
index 7917cfa..41d31f9 100644
--- a/dashboard/package-lock.json
+++ b/dashboard/package-lock.json
@@ -10,6 +10,7 @@
"license": "ISC",
"dependencies": {
"@chakra-ui/react": "^1.7.3",
+ "@emotion/core": "^11.0.0",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@types/react": "^17.0.38",
@@ -17,6 +18,7 @@
"@types/react-router-dom": "^5.3.2",
"dayjs": "^1.10.7",
"esbuild": "^0.14.9",
+ "focus-visible": "^5.2.0",
"framer-motion": "^5.5.5",
"graphql": "^16.2.0",
"lodash": "^4.17.21",
@@ -978,6 +980,11 @@
"stylis": "4.0.13"
}
},
+ "node_modules/@emotion/core": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
+ "integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
+ },
"node_modules/@emotion/hash": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
@@ -1667,6 +1674,11 @@
"node": ">=10"
}
},
+ "node_modules/focus-visible": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
+ "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
+ },
"node_modules/framer-motion": {
"version": "5.5.5",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
@@ -2517,8 +2529,7 @@
"@chakra-ui/css-reset": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
- "integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg==",
- "requires": {}
+ "integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg=="
},
"@chakra-ui/descendant": {
"version": "2.1.1",
@@ -3038,6 +3049,11 @@
"stylis": "4.0.13"
}
},
+ "@emotion/core": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
+ "integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
+ },
"@emotion/hash": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
@@ -3117,8 +3133,7 @@
"@graphql-typed-document-node/core": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
- "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
- "requires": {}
+ "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
},
"@popperjs/core": {
"version": "2.11.0",
@@ -3540,6 +3555,11 @@
"tslib": "^2.0.3"
}
},
+ "focus-visible": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
+ "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
+ },
"framer-motion": {
"version": "5.5.5",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
@@ -3823,8 +3843,7 @@
"react-icons": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
- "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==",
- "requires": {}
+ "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
},
"react-is": {
"version": "16.13.1",
@@ -4010,8 +4029,7 @@
"use-callback-ref": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
- "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
- "requires": {}
+ "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
},
"use-sidecar": {
"version": "1.0.5",
diff --git a/dashboard/package.json b/dashboard/package.json
index 9f854ba..0762191 100644
--- a/dashboard/package.json
+++ b/dashboard/package.json
@@ -12,6 +12,7 @@
"license": "ISC",
"dependencies": {
"@chakra-ui/react": "^1.7.3",
+ "@emotion/core": "^11.0.0",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@types/react": "^17.0.38",
@@ -19,6 +20,7 @@
"@types/react-router-dom": "^5.3.2",
"dayjs": "^1.10.7",
"esbuild": "^0.14.9",
+ "focus-visible": "^5.2.0",
"framer-motion": "^5.5.5",
"graphql": "^16.2.0",
"lodash": "^4.17.21",
diff --git a/dashboard/src/App.tsx b/dashboard/src/App.tsx
index 001e7a9..1f62166 100644
--- a/dashboard/src/App.tsx
+++ b/dashboard/src/App.tsx
@@ -1,4 +1,5 @@
import * as React from 'react';
+import { Fragment } from 'react';
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
import { BrowserRouter } from 'react-router-dom';
import { createClient, Provider } from 'urql';
@@ -24,6 +25,7 @@ const theme = extendTheme({
'html, body, #root': {
fontFamily: 'Avenir, Helvetica, Arial, sans-serif',
height: '100%',
+ outline: 'none',
},
},
},
@@ -36,14 +38,16 @@ const theme = extendTheme({
export default function App() {
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/dashboard/src/components/EnvComponents/AccessToken.tsx b/dashboard/src/components/EnvComponents/AccessToken.tsx
new file mode 100644
index 0000000..9fba521
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/AccessToken.tsx
@@ -0,0 +1,65 @@
+import React from "react";
+import { Flex, Stack, Text, useMediaQuery } from "@chakra-ui/react";
+import InputField from "../../components/InputField";
+import { TextInputType, TextAreaInputType } from "../../constants";
+
+const AccessToken = ({ variables, setVariables }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Access Token
+
+
+
+
+ Access Token Expiry Time:
+
+
+
+
+
+
+
+ Custom Scripts:
+
+ (Used to add custom fields in ID token)
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AccessToken;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx b/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx
new file mode 100644
index 0000000..12c85e1
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx
@@ -0,0 +1,88 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+
+import InputField from "../../components/InputField";
+import { TextInputType } from "../../constants";
+
+const DatabaseCredentials = ({ variables, setVariables }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Database Credentials
+
+
+
+ Note: Database related environment variables cannot be updated from
+ dashboard :(
+
+
+
+ DataBase Name:
+
+
+
+
+
+
+
+ DataBase Type:
+
+
+
+
+
+
+
+ DataBase URL:
+
+
+
+
+
+
+
+ );
+};
+
+export default DatabaseCredentials;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/DomainWhitelisting.tsx b/dashboard/src/components/EnvComponents/DomainWhitelisting.tsx
new file mode 100644
index 0000000..d7ed13f
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/DomainWhitelisting.tsx
@@ -0,0 +1,35 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import InputField from "../../components/InputField";
+import { ArrayInputType} from "../../constants";
+
+const DomainWhiteListing = ({ variables, setVariables }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Domain White Listing
+
+
+
+
+ Allowed Origins:
+
+
+
+
+
+
+
+ );
+};
+
+export default DomainWhiteListing;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/EmailConfiguration.tsx b/dashboard/src/components/EnvComponents/EmailConfiguration.tsx
new file mode 100644
index 0000000..17a1eed
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/EmailConfiguration.tsx
@@ -0,0 +1,114 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import InputField from "../../components/InputField";
+import { TextInputType, HiddenInputType} from "../../constants";
+const EmailConfigurations = ({
+ variables,
+ setVariables,
+ fieldVisibility,
+ setFieldVisibility,
+}: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Email Configurations
+
+
+
+
+ SMTP Host:
+
+
+
+
+
+
+
+ SMTP Port:
+
+
+
+
+
+
+
+ SMTP Username:
+
+
+
+
+
+
+
+ SMTP Password:
+
+
+
+
+
+
+
+ From Email:
+
+
+
+
+
+
+
+ );
+};
+
+export default EmailConfigurations;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/JWTConfiguration.tsx b/dashboard/src/components/EnvComponents/JWTConfiguration.tsx
new file mode 100644
index 0000000..4424725
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/JWTConfiguration.tsx
@@ -0,0 +1,154 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import {
+ HiddenInputType,
+ TextInputType,
+ TextAreaInputType,
+} from "../../constants";
+import GenerateKeysModal from "../GenerateKeysModal";
+import InputField from "../InputField";
+
+const JSTConfigurations = ({
+ variables,
+ setVariables,
+ fieldVisibility,
+ setFieldVisibility,
+ SelectInputType,
+ getData,
+ HMACEncryptionType,
+ RSAEncryptionType,
+ ECDSAEncryptionType,
+}: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+
+ return (
+
+ {" "}
+
+
+ JWT (JSON Web Tokens) Configurations
+
+
+
+
+
+
+
+
+ JWT Type:
+
+
+
+
+
+ {Object.values(HMACEncryptionType).includes(variables.JWT_TYPE) ? (
+
+
+ JWT Secret
+
+
+
+
+
+ ) : (
+ <>
+
+
+ Public Key
+
+
+
+
+
+
+
+ Private Key
+
+
+
+
+
+ >
+ )}
+
+
+
+ JWT Role Claim:
+
+
+
+
+
+
+
+
+ );
+};
+
+export default JSTConfigurations;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/OAuthConfig.tsx b/dashboard/src/components/EnvComponents/OAuthConfig.tsx
new file mode 100644
index 0000000..a235e09
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/OAuthConfig.tsx
@@ -0,0 +1,191 @@
+import React from 'react';
+import InputField from '../InputField';
+import {
+ Flex,
+ Stack,
+ Center,
+ Text,
+ Box,
+ Divider,
+ useMediaQuery,
+} from '@chakra-ui/react';
+import { FaGoogle, FaGithub, FaFacebookF } from 'react-icons/fa';
+import { TextInputType, HiddenInputType } from '../../constants';
+
+const OAuthConfig = ({
+ envVariables,
+ setVariables,
+ fieldVisibility,
+ setFieldVisibility,
+}: any) => {
+ const [isNotSmallerScreen] = useMediaQuery('(min-width:667px)');
+ return (
+
+
+
+ Your instance information
+
+
+
+
+ Client ID
+
+
+ {}}
+ inputType={TextInputType.CLIENT_ID}
+ placeholder="Client ID"
+ readOnly={true}
+ />
+
+
+
+
+ Client Secret
+
+
+
+
+
+
+
+
+ Social Media Logins
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default OAuthConfig;
diff --git a/dashboard/src/components/EnvComponents/OrganizationInfo.tsx b/dashboard/src/components/EnvComponents/OrganizationInfo.tsx
new file mode 100644
index 0000000..c5f7e36
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/OrganizationInfo.tsx
@@ -0,0 +1,60 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import InputField from "../InputField";
+import { TextInputType } from "../../constants";
+
+const OrganizationInfo = ({ variables, setVariables }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Organization Information
+
+
+
+
+ Organization Name:
+
+
+
+
+
+
+
+ Organization Logo:
+
+
+
+
+
+
+
+ );
+};
+
+export default OrganizationInfo;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/Roles.tsx b/dashboard/src/components/EnvComponents/Roles.tsx
new file mode 100644
index 0000000..ac610ab
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/Roles.tsx
@@ -0,0 +1,67 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import { ArrayInputType } from "../../constants";
+import InputField from "../InputField";
+
+const Roles = ({ variables, setVariables }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Roles
+
+
+
+
+ Roles:
+
+
+
+
+
+
+
+ Default Roles:
+
+
+
+
+
+
+
+ Protected Roles:
+
+
+
+
+
+
+
+ );
+};
+
+export default Roles;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx b/dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
new file mode 100644
index 0000000..cf39f6c
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
@@ -0,0 +1,138 @@
+import React from "react";
+import {
+ Flex,
+ Stack,
+ Center,
+ Text,
+ Input,
+ InputGroup,
+ InputRightElement,
+ useMediaQuery,
+} from "@chakra-ui/react";
+import { FaRegEyeSlash, FaRegEye } from "react-icons/fa";
+import InputField from "../InputField";
+import { HiddenInputType } from "../../constants";
+const SecurityAdminSecret = ({
+ variables,
+ setVariables,
+ fieldVisibility,
+ setFieldVisibility,
+ validateAdminSecretHandler,
+ adminSecret,
+}: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Security (Admin Secret)
+
+
+
+
+ Old Admin Secret:
+
+
+
+ validateAdminSecretHandler(event)}
+ type={
+ !fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
+ ? "password"
+ : "text"
+ }
+ />
+
+ {fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
+
+ setFieldVisibility({
+ ...fieldVisibility,
+ [HiddenInputType.OLD_ADMIN_SECRET]: false,
+ })
+ }
+ >
+
+
+ ) : (
+
+ setFieldVisibility({
+ ...fieldVisibility,
+ [HiddenInputType.OLD_ADMIN_SECRET]: true,
+ })
+ }
+ >
+
+
+ )}
+
+ }
+ />
+
+
+
+
+
+ New Admin Secret:
+
+
+
+
+
+
+
+ );
+};
+
+export default SecurityAdminSecret;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/SessionStorage.tsx b/dashboard/src/components/EnvComponents/SessionStorage.tsx
new file mode 100644
index 0000000..8570f47
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/SessionStorage.tsx
@@ -0,0 +1,36 @@
+import React from "react";
+import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
+import InputField from "../InputField";
+
+const SessionStorage = ({ variables, setVariables, RedisURL }: any) => {
+ const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
+ return (
+
+ {" "}
+
+ Session Storage
+
+
+
+
+ Redis URL:
+
+
+
+
+
+
+
+ );
+};
+
+export default SessionStorage;
\ No newline at end of file
diff --git a/dashboard/src/components/EnvComponents/UICustomization.tsx b/dashboard/src/components/EnvComponents/UICustomization.tsx
new file mode 100644
index 0000000..756c739
--- /dev/null
+++ b/dashboard/src/components/EnvComponents/UICustomization.tsx
@@ -0,0 +1,79 @@
+import React from 'react';
+import { Flex, Stack, Text } from '@chakra-ui/react';
+import InputField from '../InputField';
+import { SwitchInputType } from '../../constants';
+
+const UICustomization = ({ variables, setVariables }: any) => {
+ return (
+
+ {' '}
+
+ Disable Features
+
+
+
+
+ Disable Login Page:
+
+
+
+
+
+
+
+ Disable Email Verification:
+
+
+
+
+
+
+
+ Disable Magic Login Link:
+
+
+
+
+
+
+
+ Disable Basic Authentication:
+
+
+
+
+
+
+
+ Disable Sign Up:
+
+
+
+
+
+
+
+ );
+};
+
+export default UICustomization;
diff --git a/dashboard/src/components/InputField.tsx b/dashboard/src/components/InputField.tsx
index ede074d..8e58189 100644
--- a/dashboard/src/components/InputField.tsx
+++ b/dashboard/src/components/InputField.tsx
@@ -116,7 +116,7 @@ const InputField = ({
3 ? "scroll" : "hidden"}
+ overflowY="hidden"
+ justifyContent="start"
+ alignItems="center"
>
{variables[inputType].map((role: string, index: number) => (
@@ -220,7 +221,7 @@ const InputField = ({
size="xs"
minW="150px"
placeholder="add a new value"
- value={inputData[inputType]}
+ value={inputData[inputType] ?? ''}
onChange={(e: any) => {
setInputData({ ...inputData, [inputType]: e.target.value });
}}
diff --git a/dashboard/src/components/InviteMembersModal.tsx b/dashboard/src/components/InviteMembersModal.tsx
index 8107669..2878722 100644
--- a/dashboard/src/components/InviteMembersModal.tsx
+++ b/dashboard/src/components/InviteMembersModal.tsx
@@ -22,6 +22,7 @@ import {
InputRightElement,
Text,
Link,
+ Tooltip
} from '@chakra-ui/react';
import { useClient } from 'urql';
import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa';
@@ -186,7 +187,22 @@ const InviteMembersModal = ({
isDisabled={disabled}
size="sm"
>
- Invite Members
+
+ {disabled ? (
+
+ Invite Members
+
+ ) : (
+ "Invite Members"
+ )}
+ {" "}
diff --git a/dashboard/src/components/Menu.tsx b/dashboard/src/components/Menu.tsx
index a8e2fdd..819c665 100644
--- a/dashboard/src/components/Menu.tsx
+++ b/dashboard/src/components/Menu.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode } from 'react';
+import React, { Fragment, ReactNode } from 'react';
import {
IconButton,
Box,
@@ -17,16 +17,27 @@ import {
MenuButton,
MenuItem,
MenuList,
+ Accordion,
+ AccordionButton,
+ AccordionPanel,
+ AccordionItem,
+ useMediaQuery,
} from '@chakra-ui/react';
import {
- FiHome,
+ FiUser,
FiCode,
FiSettings,
FiMenu,
- FiUser,
FiUsers,
FiChevronDown,
} from 'react-icons/fi';
+import { BiCustomize } from 'react-icons/bi';
+import { AiOutlineKey } from 'react-icons/ai';
+import { SiOpenaccess, SiJsonwebtokens } from 'react-icons/si';
+import { MdSecurity } from 'react-icons/md';
+import { RiDatabase2Line } from 'react-icons/ri';
+import { BsCheck2Circle } from 'react-icons/bs';
+import { HiOutlineMail, HiOutlineOfficeBuilding } from 'react-icons/hi';
import { IconType } from 'react-icons';
import { ReactText } from 'react';
import { useMutation, useQuery } from 'urql';
@@ -35,14 +46,70 @@ import { useAuthContext } from '../contexts/AuthContext';
import { AdminLogout } from '../graphql/mutation';
import { MetaQuery } from '../graphql/queries';
-interface LinkItemProps {
+interface SubRoutes {
name: string;
icon: IconType;
route: string;
}
+
+interface LinkItemProps {
+ name: string;
+ icon: IconType;
+ route: string;
+ subRoutes?: SubRoutes[];
+}
const LinkItems: Array = [
- // { name: 'Home', icon: FiHome, route: '/' },
- { name: 'Environment Variables', icon: FiSettings, route: '/' },
+ {
+ name: 'Environment ',
+ icon: FiSettings,
+ route: '/',
+ subRoutes: [
+ {
+ name: 'OAuth Config',
+ icon: AiOutlineKey,
+ route: '/oauth-setting',
+ },
+
+ { name: 'Roles', icon: FiUser, route: '/roles' },
+ {
+ name: 'JWT Secrets',
+ icon: SiJsonwebtokens,
+ route: '/jwt-config',
+ },
+ {
+ name: 'Session Storage',
+ icon: RiDatabase2Line,
+ route: '/session-storage',
+ },
+ {
+ name: 'Email Configurations',
+ icon: HiOutlineMail,
+ route: '/email-config',
+ },
+ {
+ name: 'Domain White Listing',
+ icon: BsCheck2Circle,
+ route: '/whitelist-variables',
+ },
+ {
+ name: 'Organization Info',
+ icon: HiOutlineOfficeBuilding,
+ route: '/organization-info',
+ },
+ { name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
+ {
+ name: 'UI Customization',
+ icon: BiCustomize,
+ route: '/ui-customization',
+ },
+ { name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
+ {
+ name: ' Security',
+ icon: MdSecurity,
+ route: '/admin-secret',
+ },
+ ],
+ },
{ name: 'Users', icon: FiUsers, route: '/users' },
];
@@ -53,6 +120,7 @@ interface SidebarProps extends BoxProps {
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
const { pathname } = useLocation();
const [{ fetching, data }] = useQuery({ query: MetaQuery });
+ const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
return (
{
h="full"
{...rest}
>
-
+
-
+
{
- {LinkItems.map((link) => (
-
-
- {link.name}
-
-
- ))}
-
- API Playground
-
+
+
+ {LinkItems.map((link) =>
+ link?.subRoutes ? (
+
+
+
+
+
+ {link.name}
+
+
+
+
+
+
+
+
+ {link.subRoutes?.map((sublink) => (
+
+ {' '}
+
+
+ {sublink.name}
+ {' '}
+
+
+ ))}
+
+
+ ) : (
+
+ {' '}
+
+
+ {link.name}
+ {' '}
+
+
+ )
+ )}
+
+ API Playground
+
+
+
{data?.meta?.version && (
-
- Current Version: {data.meta.version}
-
+
+ {' '}
+
+ Current Version: {data.meta.version}
+
+
)}
);
@@ -119,7 +250,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
interface NavItemProps extends FlexProps {
icon: IconType;
- children: ReactText;
+ children: ReactText | JSX.Element | JSX.Element[];
}
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
return (
@@ -204,7 +335,7 @@ export const MobileNav = ({ onOpen, ...rest }: MobileProps) => {
transition="all 0.3s"
_focus={{ boxShadow: 'none' }}
>
-
+
, document.getElementById('root'));
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
diff --git a/dashboard/src/layouts/AuthLayout.tsx b/dashboard/src/layouts/AuthLayout.tsx
index dbe51ff..4c1c01f 100644
--- a/dashboard/src/layouts/AuthLayout.tsx
+++ b/dashboard/src/layouts/AuthLayout.tsx
@@ -1,20 +1,27 @@
-import { Box, Flex, Image, Text, Spinner } from '@chakra-ui/react';
+import {
+ Box,
+ Flex,
+ Image,
+ Text,
+ Spinner,
+ useMediaQuery,
+} from '@chakra-ui/react';
import React from 'react';
import { useQuery } from 'urql';
import { MetaQuery } from '../graphql/queries';
export function AuthLayout({ children }: { children: React.ReactNode }) {
const [{ fetching, data }] = useQuery({ query: MetaQuery });
+ const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
return (
-
+
) : (
<>
-
+
{children}
diff --git a/dashboard/src/pages/Environment.tsx b/dashboard/src/pages/Environment.tsx
index a6ef5a5..78f79c4 100644
--- a/dashboard/src/pages/Environment.tsx
+++ b/dashboard/src/pages/Environment.tsx
@@ -1,46 +1,35 @@
import React, { useEffect } from 'react';
-import {
- Box,
- Divider,
- Flex,
- Stack,
- Center,
- Text,
- Button,
- Input,
- InputGroup,
- InputRightElement,
- useToast,
-} from '@chakra-ui/react';
+import { useParams } from 'react-router-dom';
+import { Box, Flex, Stack, Button, useToast } from '@chakra-ui/react';
import { useClient } from 'urql';
-import {
- FaGoogle,
- FaGithub,
- FaFacebookF,
- FaSave,
- FaRegEyeSlash,
- FaRegEye,
-} from 'react-icons/fa';
+import { FaSave } from 'react-icons/fa';
import _ from 'lodash';
-import InputField from '../components/InputField';
import { EnvVariablesQuery } from '../graphql/queries';
import {
- ArrayInputType,
SelectInputType,
HiddenInputType,
TextInputType,
- TextAreaInputType,
- SwitchInputType,
HMACEncryptionType,
RSAEncryptionType,
ECDSAEncryptionType,
envVarTypes,
+ envSubViews,
} from '../constants';
import { UpdateEnvVariables } from '../graphql/mutation';
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
-import GenerateKeysModal from '../components/GenerateKeysModal';
+import OAuthConfig from '../components/EnvComponents/OAuthConfig';
+import Roles from '../components/EnvComponents/Roles';
+import JWTConfigurations from '../components/EnvComponents/JWTConfiguration';
+import SessionStorage from '../components/EnvComponents/SessionStorage';
+import EmailConfigurations from '../components/EnvComponents/EmailConfiguration';
+import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting';
+import OrganizationInfo from '../components/EnvComponents/OrganizationInfo';
+import AccessToken from '../components/EnvComponents/AccessToken';
+import UICustomization from '../components/EnvComponents/UICustomization';
+import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret';
+import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials';
-export default function Environment() {
+const Environment = () => {
const client = useClient();
const toast = useToast();
const [adminSecret, setAdminSecret] = React.useState<
@@ -100,11 +89,14 @@ export default function Environment() {
OLD_ADMIN_SECRET: false,
});
+ const { sec } = useParams();
+
async function getData() {
const {
data: { _env: envData },
} = await client.query(EnvVariablesQuery).toPromise();
setLoading(false);
+
setEnvVariables({
...envData,
OLD_ADMIN_SECRET: envData.ADMIN_SECRET,
@@ -118,7 +110,7 @@ export default function Environment() {
useEffect(() => {
getData();
- }, []);
+ }, [sec]);
const validateAdminSecretHandler = (event: any) => {
if (envVariables.OLD_ADMIN_SECRET === event.target.value) {
@@ -200,636 +192,113 @@ export default function Environment() {
});
};
- return (
-
-
- Your instance information
-
-
-
-
- Client ID
-
-
- {}}
- inputType={TextInputType.CLIENT_ID}
- placeholder="Client ID"
- readOnly={true}
- />
-
-
-
-
- Client Secret
-
-
-
-
-
-
-
-
- Social Media Logins
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Roles
-
-
-
-
- Roles:
-
-
-
-
-
-
-
- Default Roles:
-
-
-
-
-
-
-
- Protected Roles:
-
-
-
-
-
-
-
-
-
- JWT (JSON Web Tokens) Configurations
-
-
- {
+ switch (tab) {
+ case envSubViews.INSTANCE_INFO:
+ return (
+
+ );
+ case envSubViews.ROLES:
+ return (
+
+ );
+ case envSubViews.JWT_CONFIG:
+ return (
+
-
-
-
-
-
- JWT Type:
-
-
-
-
-
- {Object.values(HMACEncryptionType).includes(envVariables.JWT_TYPE) ? (
-
-
- JWT Secret
-
-
-
-
-
- ) : (
- <>
-
-
- Public Key
-
-
-
-
-
-
-
- Private Key
-
-
-
-
-
- >
- )}
-
-
- JWT Role Claim:
-
-
-
-
-
-
-
-
- Session Storage
-
-
-
-
- Redis URL:
-
-
-
-
-
-
-
-
- Email Configurations
-
-
-
-
- SMTP Host:
-
-
-
-
-
-
-
- SMTP Port:
-
-
-
-
-
-
-
- SMTP Username:
-
-
-
-
-
-
-
- SMTP Password:
-
-
-
-
-
-
-
- From Email:
-
-
-
-
-
-
-
-
- White Listing
-
-
-
-
- Allowed Origins:
-
-
-
-
-
-
-
-
- Organization Information
-
-
-
-
- Organization Name:
-
-
-
-
-
-
-
- Organization Logo:
-
-
-
-
-
-
-
-
- Access Token
-
-
-
-
- Access Token Expiry Time:
-
-
-
-
-
-
-
- Custom Scripts:
- Used to add custom fields in ID token
-
-
-
-
-
-
-
-
- Disable Features
-
-
-
-
- Disable Login Page:
-
-
-
-
-
-
-
- Disable Email Verification:
-
-
-
-
-
-
-
- Disable Magic Login Link:
-
-
-
-
-
-
-
- Disable Basic Authentication:
-
-
-
-
-
-
-
- Disable Sign Up:
-
-
-
-
-
-
-
-
- Danger
-
-
-
-
- Note: Database related environment variables cannot be updated from
- dashboard :(
-
-
-
- DataBase Name:
-
-
-
-
-
-
-
- DataBase Type:
-
-
-
-
-
-
-
- DataBase URL:
-
-
-
-
-
-
-
-
- Old Admin Secret:
-
-
-
- validateAdminSecretHandler(event)}
- type={
- !fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
- ? 'password'
- : 'text'
- }
- />
-
- {fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
-
- setFieldVisibility({
- ...fieldVisibility,
- [HiddenInputType.OLD_ADMIN_SECRET]: false,
- })
- }
- >
-
-
- ) : (
-
- setFieldVisibility({
- ...fieldVisibility,
- [HiddenInputType.OLD_ADMIN_SECRET]: true,
- })
- }
- >
-
-
- )}
-
- }
- />
-
-
-
-
-
- New Admin Secret:
-
-
-
-
-
-
-
-
+ );
+ case envSubViews.SESSION_STORAGE:
+ return (
+
+ );
+ case envSubViews.EMAIL_CONFIG:
+ return (
+
+ );
+ case envSubViews.WHITELIST_VARIABLES:
+ return (
+
+ );
+ case envSubViews.ORGANIZATION_INFO:
+ return (
+
+ );
+ case envSubViews.ACCESS_TOKEN:
+ return (
+
+ );
+ case envSubViews.UI_CUSTOMIZATION:
+ return (
+
+ );
+ case envSubViews.ADMIN_SECRET:
+ return (
+
+ );
+ case envSubViews.DB_CRED:
+ return (
+
+ );
+ default:
+ return (
+
+ );
+ }
+ };
+ return (
+
+ {renderComponent(sec)}
+
}
@@ -844,4 +313,6 @@ export default function Environment() {
);
-}
+};
+
+export default Environment;
diff --git a/dashboard/src/routes/index.tsx b/dashboard/src/routes/index.tsx
index 30cec3a..f611e92 100644
--- a/dashboard/src/routes/index.tsx
+++ b/dashboard/src/routes/index.tsx
@@ -14,6 +14,7 @@ export const AppRoutes = () => {
if (isLoggedIn) {
return (
+
>}>
{
}
>
- } />
- } />
- } />
- } />
+ }>
+ } />
+ } />
+
+ } />
+ } />
+
);
}
return (