mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 21:51:56 +00:00
Wired access controls for environemnts to frontend
This commit is contained in:
@@ -13,6 +13,7 @@ export interface IMembershipOrg {
|
||||
organization: string;
|
||||
role: 'owner' | 'admin' | 'member';
|
||||
status: 'invited' | 'accepted';
|
||||
deniedPermissions: any[];
|
||||
}
|
||||
/**
|
||||
* This route lets us get all the users in an org.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us get the environments that a certain user has acess to in a certain project
|
||||
* @param {string} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getWorkspaceEnvironments = ({ workspaceId }: { workspaceId: string }) =>
|
||||
SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/environments`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res?.status === 200) {
|
||||
return (await res.json()).accessibleEnvironments;
|
||||
}
|
||||
console.log('Failed to get accessible environments');
|
||||
return undefined;
|
||||
});
|
||||
|
||||
export default getWorkspaceEnvironments;
|
||||
@@ -41,11 +41,13 @@ import updateSecrets from '../api/files/UpdateSecrets';
|
||||
import getUser from '../api/user/getUser';
|
||||
import checkUserAction from '../api/userActions/checkUserAction';
|
||||
import registerUserAction from '../api/userActions/registerUserAction';
|
||||
import getWorkspaceEnvironments from '../api/workspace/getWorkspaceEnvironments';
|
||||
import getWorkspaces from '../api/workspace/getWorkspaces';
|
||||
|
||||
type WorkspaceEnv = {
|
||||
name: string;
|
||||
slug: string;
|
||||
isWriteDenied: boolean;
|
||||
};
|
||||
|
||||
interface SecretDataProps {
|
||||
@@ -133,7 +135,8 @@ export default function Dashboard() {
|
||||
const [selectedSnapshotEnv, setSelectedSnapshotEnv] = useState<WorkspaceEnv>();
|
||||
const [selectedEnv, setSelectedEnv] = useState<WorkspaceEnv>({
|
||||
name: '',
|
||||
slug: ''
|
||||
slug: '',
|
||||
isWriteDenied: false
|
||||
});
|
||||
const [atSecretAreaTop, setAtSecretsAreaTop] = useState(true);
|
||||
const secretsTop = useRef<HTMLDivElement>(null);
|
||||
@@ -214,9 +217,10 @@ export default function Dashboard() {
|
||||
router.push(`/dashboard/${userWorkspaces?.[0]?._id}`);
|
||||
}
|
||||
|
||||
setWorkspaceEnvs(workspace?.environments || []);
|
||||
const accessibleEnvironments = await getWorkspaceEnvironments({ workspaceId });
|
||||
setWorkspaceEnvs(accessibleEnvironments || []);
|
||||
// set env
|
||||
const env = workspace?.environments?.[0] || {
|
||||
const env = accessibleEnvironments?.[0] || {
|
||||
name: 'unknown',
|
||||
slug: 'unkown'
|
||||
};
|
||||
@@ -351,6 +355,7 @@ export default function Dashboard() {
|
||||
findDuplicates(data!.map((item: SecretDataProps) => item.key)).length > 0;
|
||||
|
||||
if (nameErrors) {
|
||||
setSaveLoading(false);
|
||||
return createNotification({
|
||||
text: 'Solve all name errors before saving secrets.',
|
||||
type: 'error'
|
||||
@@ -358,12 +363,21 @@ export default function Dashboard() {
|
||||
}
|
||||
|
||||
if (duplicatesExist) {
|
||||
setSaveLoading(false);
|
||||
return createNotification({
|
||||
text: 'Remove duplicated secret names before saving.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedEnv.isWriteDenied) {
|
||||
setSaveLoading(false);
|
||||
return createNotification({
|
||||
text: 'You are not allowed to edit this environment',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
// Once "Save changes" is clicked, disable that button
|
||||
setButtonReady(false);
|
||||
|
||||
@@ -580,7 +594,8 @@ export default function Dashboard() {
|
||||
setSelectedEnv(
|
||||
workspaceEnvs.find(({ name }) => envName === name) || {
|
||||
name: 'unknown',
|
||||
slug: 'unknown'
|
||||
slug: 'unknown',
|
||||
isWriteDenied: false
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -660,7 +675,8 @@ export default function Dashboard() {
|
||||
setSelectedEnv(
|
||||
workspaceEnvs.find(({ name }) => envName === name) || {
|
||||
name: 'unknown',
|
||||
slug: 'unknown'
|
||||
slug: 'unknown',
|
||||
isWriteDenied: false
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -673,7 +689,8 @@ export default function Dashboard() {
|
||||
setSelectedSnapshotEnv(
|
||||
workspaceEnvs.find(({ name }) => envName === name) || {
|
||||
name: 'unknown',
|
||||
slug: 'unknown'
|
||||
slug: 'unknown',
|
||||
isWriteDenied: false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import Button from '@app/components/basic/buttons/Button';
|
||||
import AddProjectMemberDialog from '@app/components/basic/dialog/AddProjectMemberDialog';
|
||||
import UserTable from '@app/components/basic/table/UserTable';
|
||||
import ProjectUsersTable from '@app/components/basic/table/ProjectUsersTable';
|
||||
import NavHeader from '@app/components/navigation/NavHeader';
|
||||
import guidGenerator from '@app/components/utilities/randomId';
|
||||
import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps';
|
||||
@@ -33,6 +33,7 @@ interface UserProps {
|
||||
}
|
||||
|
||||
interface MembershipProps {
|
||||
deniedPermissions: any[];
|
||||
user: UserProps;
|
||||
inviteEmail: string;
|
||||
role: string;
|
||||
@@ -76,6 +77,7 @@ export default function Users() {
|
||||
status: membership?.status,
|
||||
userId: membership.user?._id,
|
||||
membershipId: membership._id,
|
||||
deniedPermissions: membership.deniedPermissions,
|
||||
publicKey: membership.user?.publicKey
|
||||
}));
|
||||
setUserList(tempUserList);
|
||||
@@ -144,7 +146,7 @@ export default function Users() {
|
||||
};
|
||||
|
||||
return userList ? (
|
||||
<div className="bg-bunker-800 md:h-screen flex flex-col justify-start">
|
||||
<div className="bg-bunker-800 md:h-screen flex flex-col justify-start max-w-[calc(100vw-240px)]">
|
||||
<Head>
|
||||
<title>{t('common:head-title', { title: t('settings-members:title') })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
@@ -168,7 +170,7 @@ export default function Users() {
|
||||
setEmail={setEmail}
|
||||
/>
|
||||
{/* <DeleteUserDialog isOpen={isDeleteOpen} closeModal={closeDeleteModal} submitModal={deleteMembership} userIdToBeDeleted={userIdToBeDeleted}/> */}
|
||||
<div className="px-6 pb-1 w-full flex flex-row items-start min-w-6xl max-w-6xl">
|
||||
<div className="px-6 pb-1 w-full flex flex-row items-start">
|
||||
<div className="h-10 w-full bg-white/5 mt-2 rounded-md flex flex-row items-center">
|
||||
<FontAwesomeIcon
|
||||
className="bg-white/5 rounded-l-md py-3 pl-4 pr-2 text-gray-400"
|
||||
@@ -191,14 +193,12 @@ export default function Users() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="block overflow-y-auto min-w-6xl max-w-6xl px-6">
|
||||
<UserTable
|
||||
<div className="block overflow-x-scroll px-6 pb-6 no-scrollbar no-scrollbar::-webkit-scrollbar">
|
||||
<ProjectUsersTable
|
||||
userData={userList}
|
||||
changeData={setUserList}
|
||||
myUser={personalEmail}
|
||||
filter={searchUsers}
|
||||
resendInvite={submitAddModal}
|
||||
isOrg={false}
|
||||
// onClick={openDeleteModal}
|
||||
// deleteUser={deleteMembership}
|
||||
// setUserIdToBeDeleted={setUserIdToBeDeleted}
|
||||
|
||||
Reference in New Issue
Block a user