Merge branch 'authorizerdev/authorizer:main' into main

This commit is contained in:
egor.medvedev
2022-03-25 16:13:46 +03:00
66 changed files with 3244 additions and 158 deletions

View File

@@ -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;
OLD_ADMIN_SECRET: string;
DATABASE_NAME: string;
DATABASE_TYPE: string;
DATABASE_URL: string;
ACCESS_TOKEN_EXPIRY_TIME: string;
}
import GenerateKeysModal from '../components/GenerateKeysModal';
export default function Environment() {
const client = useClient();
@@ -115,6 +80,7 @@ export default function Environment() {
DISABLE_MAGIC_LINK_LOGIN: false,
DISABLE_EMAIL_VERIFICATION: false,
DISABLE_BASIC_AUTHENTICATION: false,
DISABLE_SIGN_UP: false,
OLD_ADMIN_SECRET: '',
DATABASE_NAME: '',
DATABASE_TYPE: '',
@@ -134,32 +100,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) => {
@@ -230,6 +188,8 @@ export default function Environment() {
disableInputField: true,
});
getData();
toast({
title: `Successfully updated ${
Object.keys(updatedEnvVariables).length
@@ -256,7 +216,7 @@ export default function Environment() {
setVariables={() => {}}
inputType={TextInputType.CLIENT_ID}
placeholder="Client ID"
isDisabled={true}
readOnly={true}
/>
</Center>
</Flex>
@@ -272,7 +232,7 @@ export default function Environment() {
setFieldVisibility={setFieldVisibility}
inputType={HiddenInputType.CLIENT_SECRET}
placeholder="Client Secret"
isDisabled={true}
readOnly={true}
/>
</Center>
</Flex>
@@ -410,9 +370,22 @@ export default function Environment() {
</Flex>
</Stack>
<Divider marginTop="2%" marginBottom="2%" />
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
JWT (JSON Web Tokens) Configurations
</Text>
<Flex
width="100%"
justifyContent="space-between"
alignItems="center"
paddingTop="2%"
>
<Text fontSize="md" fontWeight="bold">
JWT (JSON Web Tokens) Configurations
</Text>
<Flex>
<GenerateKeysModal
jwtType={envVariables.JWT_TYPE}
getData={getData}
/>
</Flex>
</Flex>
<Stack spacing={6} padding="2% 0%">
<Flex>
<Flex w="30%" justifyContent="start" alignItems="center">
@@ -712,6 +685,18 @@ export default function Environment() {
/>
</Flex>
</Flex>
<Flex>
<Flex w="30%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Disable Sign Up:</Text>
</Flex>
<Flex justifyContent="start" w="70%">
<InputField
variables={envVariables}
setVariables={setEnvVariables}
inputType={SwitchInputType.DISABLE_SIGN_UP}
/>
</Flex>
</Flex>
</Stack>
<Divider marginTop="2%" marginBottom="2%" />
<Text fontSize="md" paddingTop="2%" fontWeight="bold">

View File

@@ -38,10 +38,11 @@ import {
FaExclamationCircle,
FaAngleDown,
} from 'react-icons/fa';
import { UserDetailsQuery } from '../graphql/queries';
import { UpdateUser } from '../graphql/mutation';
import { EmailVerificationQuery, UserDetailsQuery } from '../graphql/queries';
import { EnableAccess, RevokeAccess, UpdateUser } from '../graphql/mutation';
import EditUserModal from '../components/EditUserModal';
import DeleteUserModal from '../components/DeleteUserModal';
import InviteMembersModal from '../components/InviteMembersModal';
interface paginationPropTypes {
limit: number;
@@ -66,6 +67,12 @@ interface userDataTypes {
signup_methods: string;
roles: [string];
created_at: number;
revoked_timestamp: number;
}
const enum updateAccessActions {
REVOKE = 'REVOKE',
ENABLE = 'ENABLE',
}
const getMaxPages = (pagination: paginationPropTypes) => {
@@ -101,6 +108,8 @@ export default function Users() {
});
const [userList, setUserList] = React.useState<userDataTypes[]>([]);
const [loading, setLoading] = React.useState<boolean>(false);
const [disableInviteMembers, setDisableInviteMembers] =
React.useState<boolean>(true);
const updateUserList = async () => {
setLoading(true);
const { data } = await client
@@ -132,8 +141,18 @@ export default function Users() {
}
setLoading(false);
};
const checkEmailVerification = async () => {
setLoading(true);
const { data } = await client.query(EmailVerificationQuery).toPromise();
if (data?._env) {
const { DISABLE_EMAIL_VERIFICATION } = data._env;
setDisableInviteMembers(DISABLE_EMAIL_VERIFICATION);
}
setLoading(false);
};
React.useEffect(() => {
updateUserList();
checkEmailVerification();
}, []);
React.useEffect(() => {
updateUserList();
@@ -171,12 +190,77 @@ export default function Users() {
}
updateUserList();
};
const updateAccessHandler = async (
id: string,
action: updateAccessActions
) => {
switch (action) {
case updateAccessActions.ENABLE:
const enableAccessRes = await client
.mutation(EnableAccess, {
param: {
user_id: id,
},
})
.toPromise();
if (enableAccessRes.error) {
toast({
title: 'User access enable failed',
isClosable: true,
status: 'error',
position: 'bottom-right',
});
} else {
toast({
title: 'User access enabled successfully',
isClosable: true,
status: 'success',
position: 'bottom-right',
});
}
updateUserList();
break;
case updateAccessActions.REVOKE:
const revokeAccessRes = await client
.mutation(RevokeAccess, {
param: {
user_id: id,
},
})
.toPromise();
if (revokeAccessRes.error) {
toast({
title: 'User access revoke failed',
isClosable: true,
status: 'error',
position: 'bottom-right',
});
} else {
toast({
title: 'User access revoked successfully',
isClosable: true,
status: 'success',
position: 'bottom-right',
});
}
updateUserList();
break;
default:
break;
}
};
return (
<Box m="5" py="5" px="10" bg="white" rounded="md">
<Flex margin="2% 0" justifyContent="space-between" alignItems="center">
<Text fontSize="md" fontWeight="bold">
Users
</Text>
<InviteMembersModal
disabled={disableInviteMembers}
updateUserList={updateUserList}
/>
</Flex>
{!loading ? (
userList.length > 0 ? (
@@ -188,6 +272,7 @@ export default function Users() {
<Th>Signup Methods</Th>
<Th>Roles</Th>
<Th>Verified</Th>
<Th>Access</Th>
<Th>Actions</Th>
</Tr>
</Thead>
@@ -196,7 +281,7 @@ export default function Users() {
const { email_verified, created_at, ...rest }: any = user;
return (
<Tr key={user.id} style={{ fontSize: 14 }}>
<Td>{user.email}</Td>
<Td maxW="300">{user.email}</Td>
<Td>
{dayjs(user.created_at * 1000).format('MMM DD, YYYY')}
</Td>
@@ -211,6 +296,15 @@ export default function Users() {
{user.email_verified.toString()}
</Tag>
</Td>
<Td>
<Tag
size="sm"
variant="outline"
colorScheme={user.revoked_timestamp ? 'red' : 'green'}
>
{user.revoked_timestamp ? 'Revoked' : 'Enabled'}
</Tag>
</Td>
<Td>
<Menu>
<MenuButton as={Button} variant="unstyled" size="sm">
@@ -240,6 +334,29 @@ export default function Users() {
user={rest}
updateUserList={updateUserList}
/>
{user.revoked_timestamp ? (
<MenuItem
onClick={() =>
updateAccessHandler(
user.id,
updateAccessActions.ENABLE
)
}
>
Enable Access
</MenuItem>
) : (
<MenuItem
onClick={() =>
updateAccessHandler(
user.id,
updateAccessActions.REVOKE
)
}
>
Revoke Access
</MenuItem>
)}
</MenuList>
</Menu>
</Td>