Skip to content

Commit

Permalink
Merge pull request #312 from Infisical/secret-tagging
Browse files Browse the repository at this point in the history
Added tags to secrets in the dashboard
  • Loading branch information
vmatsiiako authored Feb 8, 2023
2 parents d8889be + ace0e9c commit c84add0
Show file tree
Hide file tree
Showing 32 changed files with 709 additions and 109 deletions.
15 changes: 15 additions & 0 deletions backend/src/controllers/v2/secretsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
secretCommentCiphertext: string;
secretCommentIV: string;
secretCommentTag: string;
tags: string[]
}

Expand All @@ -115,6 +118,9 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
}: secretsToCreateType) => {
return ({
Expand All @@ -129,6 +135,9 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
});
})
Expand Down Expand Up @@ -160,6 +169,9 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueIV,
secretValueTag,
secretValueHash,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
}) => ({
_id: new Types.ObjectId(),
Expand All @@ -178,6 +190,9 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueIV,
secretValueTag,
secretValueHash,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
}))
});
Expand Down
4 changes: 2 additions & 2 deletions backend/src/controllers/v2/tagController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ export const deleteWorkspaceTag = async (req: Request, res: Response) => {
UnauthorizedRequestError({ message: 'Failed to validate membership' });
}

await Tag.findByIdAndDelete(tagId)
const result = await Tag.findByIdAndDelete(tagId);

res.sendStatus(200)
res.json(result);
}

export const getWorkspaceTags = async (req: Request, res: Response) => {
Expand Down
8 changes: 7 additions & 1 deletion backend/src/ee/controllers/v1/secretSnapshotController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ export const getSecretSnapshot = async (req: Request, res: Response) => {

secretSnapshot = await SecretSnapshot
.findById(secretSnapshotId)
.populate('secretVersions');
.populate({
path: 'secretVersions',
populate: {
path: 'tags',
model: 'Tag',
}
});

if (!secretSnapshot) throw new Error('Failed to find secret snapshot');

Expand Down
10 changes: 10 additions & 0 deletions frontend/public/data/frequentInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
export interface Tag {
_id: string;
name: string;
slug: string;
user: string;
workspace: string;
createdAt: string;
}

export interface SecretDataProps {
pos: number;
key: string;
value: string;
valueOverride: string | undefined;
id: string;
comment: string;
tags: Tag[];
}
8 changes: 4 additions & 4 deletions frontend/src/components/basic/dialog/AddWorkspaceDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const AddWorkspaceDialog = ({
return (
<div>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-20" onClose={closeModal}>
<Dialog as="div" className="relative z-[100]" onClose={closeModal}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
Expand All @@ -49,7 +49,7 @@ const AddWorkspaceDialog = ({
<div className="fixed inset-0 bg-black bg-opacity-70" />
</Transition.Child>

<div className="fixed inset-0 overflow-y-auto z-50">
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
Expand All @@ -60,7 +60,7 @@ const AddWorkspaceDialog = ({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-bunker-800 border border-gray-700 p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md bg-bunker-800 border border-gray-700 p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-400"
Expand All @@ -69,7 +69,7 @@ const AddWorkspaceDialog = ({
</Dialog.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">
This project will contain your environmental variables.
This project will contain your secrets and configs.
</p>
</div>
<div className="max-h-28 mt-4">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/basic/table/EnvironmentsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
</div>
<div className="w-48">
<Button
text="Add New Env"
text="Add New Environment"
onButtonPressed={() => {
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
handlePopUpOpen('createUpdateEnv');
Expand Down
61 changes: 61 additions & 0 deletions frontend/src/components/dashboard/AddTagsMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Fragment } from 'react';
import { useRouter } from 'next/router';
import { faCheckSquare, faPlus, faSquare } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Menu, Transition } from '@headlessui/react';
import { Tag } from 'public/data/frequentInterfaces';

/**
* This is the menu that is used to download secrets as .env ad .yml files (in future we may have more options)
* @param {object} obj
* @param {SecretDataProps[]} obj.data -
*
*/
const AddTagsMenu = ({ allTags, currentTags, modifyTags, position }: { allTags: Tag[]; currentTags: Tag[]; modifyTags: (value: Tag[], position: number) => void; position: number; }) => {
const router = useRouter();
return (
<Menu as="div" className="ml-2 relative inline-block text-left">
<Menu.Button
as="div"
className="flex justify-center items-center font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"
>
<div className='bg-mineshaft/30 cursor-pointer rounded-sm text-sm text-mineshaft-200/50 hover:bg-mineshaft/70 duration-200 flex items-center'>
<FontAwesomeIcon icon={faPlus} className="p-[0.28rem]"/>
{currentTags.length > 2 && <span className='pr-2'>{currentTags.length - 2}</span>}
</div>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute z-[90] text-sm drop-shadow-xl right-0 mt-0.5 w-[12rem] origin-top-right rounded-md bg-mineshaft-600 border border-mineshaft-500 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none p-1 space-y-1">
{allTags?.map((tag) => { return (
<Menu.Item key={tag._id}>
<button
type="button"
className={`${currentTags.map(currentTag => currentTag.name).includes(tag.name) ? "opacity-30 cursor-default" : "hover:bg-mineshaft-700"} w-full text-left bg-mineshaft-800 px-2 py-0.5 text-bunker-200 rounded-sm flex items-center`}
onClick={() => {if (!currentTags.map(currentTag => currentTag.name).includes(tag.name)) {modifyTags(currentTags.concat([tag]), position)}}}
>
{currentTags.map(currentTag => currentTag.name).includes(tag.name) ? <FontAwesomeIcon icon={faCheckSquare} className="text-xs mr-2 text-primary"/> : <FontAwesomeIcon icon={faSquare} className="text-xs mr-2"/>} {tag.name}
</button>
</Menu.Item>
)})}
<button
type="button"
className='w-full text-left bg-mineshaft-800 hover:bg-primary hover:text-black duration-200 px-2 py-0.5 text-bunker-200 rounded-sm'
onClick={() => router.push(`/settings/project/${String(router.query.id)}`)}
>
<FontAwesomeIcon icon={faPlus} className="mr-2 text-xs" />Add more tags
</button>
</Menu.Items>
</Transition>
</Menu>
);
};

export default AddTagsMenu;
7 changes: 3 additions & 4 deletions frontend/src/components/dashboard/DashboardInputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { faCircle, faExclamationCircle, faEye, faLayerGroup } from '@fortawesome
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import guidGenerator from '../utilities/randomId';
import { Button } from '../v2';
import { HoverObject } from '../v2/HoverCard';

const REGEX = /([$]{.*?})/g;
Expand Down Expand Up @@ -99,8 +98,8 @@ const DashboardInputField = ({
)}
{!error && <div className={`absolute right-0 top-0 text-red z-50 ${
overrideEnabled ? 'visible group-hover:bg-mineshaft-700' : 'invisible group-hover:visible bg-mineshaft-700'
} cursor-pointer duration-0`}>
<Button variant="plain" onClick={() => {
} cursor-pointer duration-0 h-10 flex items-center px-2`}>
<button type="button" onClick={() => {
if (modifyValueOverride) {
if (overrideEnabled === false) {
modifyValueOverride('', position);
Expand All @@ -114,7 +113,7 @@ const DashboardInputField = ({
icon={faLayerGroup}
color={overrideEnabled ? 'primary' : 'bunker-400'}
/>
</Button>
</button>
</div>}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/dashboard/DeleteActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const DeleteActionButton = ({ onSubmit, isPlain }: Props) => {
<div className={`${
!isPlain
? 'bg-[#9B3535] opacity-70 hover:opacity-100 w-[4.5rem] h-[2.5rem] rounded-md duration-200 ml-2'
: 'cursor-pointer w-[2.35rem] h-[2.35rem] flex items-center justfy-center'}`}>
: 'cursor-pointer w-[1.5rem] h-[2.35rem] mr-2 flex items-center justfy-center'}`}>
{isPlain
? <div
onKeyDown={() => null}
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/dashboard/DropZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const DropZone = ({
key,
value: keyPairs[key as keyof typeof keyPairs].value,
comment: keyPairs[key as keyof typeof keyPairs].comments.join('\n'),
type: 'shared'
type: 'shared',
tags: []
}));
break;
}
Expand All @@ -86,7 +87,8 @@ const DropZone = ({
key,
value: keyPairs[key as keyof typeof keyPairs]?.toString() ?? '',
comment,
type: 'shared'
type: 'shared',
tags: []
};
});
break;
Expand Down
Loading

0 comments on commit c84add0

Please sign in to comment.