diff --git a/dashboard/src/components/GenerateKeysModal.tsx b/dashboard/src/components/GenerateKeysModal.tsx new file mode 100644 index 0000000..213579f --- /dev/null +++ b/dashboard/src/components/GenerateKeysModal.tsx @@ -0,0 +1,222 @@ +import React from 'react'; +import { + Button, + Center, + Flex, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + useDisclosure, + Text, + useToast, + Input, +} from '@chakra-ui/react'; +import { useClient } from 'urql'; +import { FaSave } from 'react-icons/fa'; +import { + ECDSAEncryptionType, + HMACEncryptionType, + RSAEncryptionType, + SelectInputType, + TextAreaInputType, +} from '../constants'; +import InputField from './InputField'; +import { GenerateKeys, UpdateEnvVariables } from '../graphql/mutation'; + +interface propTypes { + jwtType: string; + getData: Function; +} + +interface stateVarTypes { + JWT_TYPE: string; + JWT_SECRET: string; + JWT_PRIVATE_KEY: string; + JWT_PUBLIC_KEY: string; +} + +const initState: stateVarTypes = { + JWT_TYPE: '', + JWT_SECRET: '', + JWT_PRIVATE_KEY: '', + JWT_PUBLIC_KEY: '', +}; + +const GenerateKeysModal = ({ jwtType, getData }: propTypes) => { + const client = useClient(); + const toast = useToast(); + const { isOpen, onOpen, onClose } = useDisclosure(); + const [stateVariables, setStateVariables] = React.useState({ + ...initState, + }); + React.useEffect(() => { + if (isOpen) { + setStateVariables({ ...initState, JWT_TYPE: jwtType }); + } + }, [isOpen]); + const fetchKeys = async () => { + const res = await client + .mutation(GenerateKeys, { params: { type: stateVariables.JWT_TYPE } }) + .toPromise(); + if (res?.error) { + toast({ + title: 'Error occurred generating jwt keys', + isClosable: true, + status: 'error', + position: 'bottom-right', + }); + closeHandler(); + } else { + setStateVariables({ + ...stateVariables, + JWT_SECRET: res?.data?._generate_jwt_keys?.secret || '', + JWT_PRIVATE_KEY: res?.data?._generate_jwt_keys?.private_key || '', + JWT_PUBLIC_KEY: res?.data?._generate_jwt_keys?.public_key || '', + }); + } + }; + React.useEffect(() => { + if (isOpen && stateVariables.JWT_TYPE) { + fetchKeys(); + } + }, [stateVariables.JWT_TYPE]); + const saveHandler = async () => { + const res = await client + .mutation(UpdateEnvVariables, { params: { ...stateVariables } }) + .toPromise(); + + if (res.error) { + toast({ + title: 'Error occurred setting jwt keys', + isClosable: true, + status: 'error', + position: 'bottom-right', + }); + + return; + } + toast({ + title: 'JWT keys updated successfully', + isClosable: true, + status: 'success', + position: 'bottom-right', + }); + closeHandler(); + }; + + const closeHandler = () => { + setStateVariables({ ...initState }); + onClose(); + getData(); + }; + return ( + <> + + + + + New JWT keys + + + + + JWT Type: + + + + {Object.values(HMACEncryptionType).includes( + stateVariables.JWT_TYPE + ) ? ( + + + JWT Secret + +
+ + setStateVariables({ + ...stateVariables, + JWT_SECRET: event.target.value, + }) + } + /> +
+
+ ) : ( + <> + + + Public Key + +
+ +
+
+ + + Private Key + +
+ +
+
+ + )} +
+ + + + +
+
+ + ); +}; + +export default GenerateKeysModal; diff --git a/dashboard/src/components/InviteMembersModal.tsx b/dashboard/src/components/InviteMembersModal.tsx index bd3642d..8107669 100644 --- a/dashboard/src/components/InviteMembersModal.tsx +++ b/dashboard/src/components/InviteMembersModal.tsx @@ -26,7 +26,6 @@ import { import { useClient } from 'urql'; import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa'; import { useDropzone } from 'react-dropzone'; -import { escape } from 'lodash'; import { validateEmail, validateURI } from '../utils'; import { InviteMembers } from '../graphql/mutation'; import { ArrayInputOperations } from '../constants'; diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts index 5fc9e5a..1ed810d 100644 --- a/dashboard/src/constants.ts +++ b/dashboard/src/constants.ts @@ -89,3 +89,40 @@ export const ECDSAEncryptionType = { ES384: 'ES384', ES512: 'ES512', }; + +export interface envVarTypes { + GOOGLE_CLIENT_ID: string; + GOOGLE_CLIENT_SECRET: string; + GITHUB_CLIENT_ID: string; + GITHUB_CLIENT_SECRET: string; + FACEBOOK_CLIENT_ID: string; + FACEBOOK_CLIENT_SECRET: string; + ROLES: [string] | []; + DEFAULT_ROLES: [string] | []; + PROTECTED_ROLES: [string] | []; + JWT_TYPE: string; + JWT_SECRET: string; + JWT_ROLE_CLAIM: string; + JWT_PRIVATE_KEY: string; + JWT_PUBLIC_KEY: string; + REDIS_URL: string; + SMTP_HOST: string; + SMTP_PORT: string; + SMTP_USERNAME: string; + SMTP_PASSWORD: string; + SENDER_EMAIL: string; + ALLOWED_ORIGINS: [string] | []; + ORGANIZATION_NAME: string; + ORGANIZATION_LOGO: string; + CUSTOM_ACCESS_TOKEN_SCRIPT: string; + ADMIN_SECRET: string; + DISABLE_LOGIN_PAGE: boolean; + DISABLE_MAGIC_LINK_LOGIN: boolean; + DISABLE_EMAIL_VERIFICATION: boolean; + DISABLE_BASIC_AUTHENTICATION: boolean; + DISABLE_SIGN_UP: boolean; + OLD_ADMIN_SECRET: string; + DATABASE_NAME: string; + DATABASE_TYPE: string; + DATABASE_URL: string; +} diff --git a/dashboard/src/graphql/mutation/index.ts b/dashboard/src/graphql/mutation/index.ts index dcadcc3..46c5fcb 100644 --- a/dashboard/src/graphql/mutation/index.ts +++ b/dashboard/src/graphql/mutation/index.ts @@ -69,3 +69,13 @@ export const EnableAccess = ` } } `; + +export const GenerateKeys = ` + mutation generateKeys($params: GenerateJWTKeysInput!) { + _generate_jwt_keys(params: $params) { + secret + public_key + private_key + } + } +`; diff --git a/dashboard/src/pages/Environment.tsx b/dashboard/src/pages/Environment.tsx index f3df0e6..352bde5 100644 --- a/dashboard/src/pages/Environment.tsx +++ b/dashboard/src/pages/Environment.tsx @@ -34,46 +34,11 @@ import { HMACEncryptionType, RSAEncryptionType, ECDSAEncryptionType, + envVarTypes, } from '../constants'; import { UpdateEnvVariables } from '../graphql/mutation'; import { getObjectDiff, capitalizeFirstLetter } from '../utils'; - -interface envVarTypes { - GOOGLE_CLIENT_ID: string; - GOOGLE_CLIENT_SECRET: string; - GITHUB_CLIENT_ID: string; - GITHUB_CLIENT_SECRET: string; - FACEBOOK_CLIENT_ID: string; - FACEBOOK_CLIENT_SECRET: string; - ROLES: [string] | []; - DEFAULT_ROLES: [string] | []; - PROTECTED_ROLES: [string] | []; - JWT_TYPE: string; - JWT_SECRET: string; - JWT_ROLE_CLAIM: string; - JWT_PRIVATE_KEY: string; - JWT_PUBLIC_KEY: string; - REDIS_URL: string; - SMTP_HOST: string; - SMTP_PORT: string; - SMTP_USERNAME: string; - SMTP_PASSWORD: string; - SENDER_EMAIL: string; - ALLOWED_ORIGINS: [string] | []; - ORGANIZATION_NAME: string; - ORGANIZATION_LOGO: string; - CUSTOM_ACCESS_TOKEN_SCRIPT: string; - ADMIN_SECRET: string; - DISABLE_LOGIN_PAGE: boolean; - DISABLE_MAGIC_LINK_LOGIN: boolean; - DISABLE_EMAIL_VERIFICATION: boolean; - DISABLE_BASIC_AUTHENTICATION: boolean; - DISABLE_SIGN_UP: boolean; - OLD_ADMIN_SECRET: string; - DATABASE_NAME: string; - DATABASE_TYPE: string; - DATABASE_URL: string; -} +import GenerateKeysModal from '../components/GenerateKeysModal'; export default function Environment() { const client = useClient(); @@ -134,32 +99,24 @@ export default function Environment() { OLD_ADMIN_SECRET: false, }); + async function getData() { + const { + data: { _env: envData }, + } = await client.query(EnvVariablesQuery).toPromise(); + setLoading(false); + setEnvVariables({ + ...envData, + OLD_ADMIN_SECRET: envData.ADMIN_SECRET, + ADMIN_SECRET: '', + }); + setAdminSecret({ + value: '', + disableInputField: true, + }); + } + useEffect(() => { - let isMounted = true; - async function getData() { - const { - data: { _env: envData }, - } = await client.query(EnvVariablesQuery).toPromise(); - - if (isMounted) { - setLoading(false); - setEnvVariables({ - ...envData, - OLD_ADMIN_SECRET: envData.ADMIN_SECRET, - ADMIN_SECRET: '', - }); - setAdminSecret({ - value: '', - disableInputField: true, - }); - } - } - getData(); - - return () => { - isMounted = false; - }; }, []); const validateAdminSecretHandler = (event: any) => { @@ -410,9 +367,22 @@ export default function Environment() { - - JWT (JSON Web Tokens) Configurations - + + + JWT (JSON Web Tokens) Configurations + + + + + diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index 3f0444e..51b2314 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -129,7 +129,5 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } -type ( - mutationResolver struct{ *Resolver } - queryResolver struct{ *Resolver } -) +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver }