mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #292 from HasanMansoor4/auto-capitalization-toggle
Auto capitalization toggle for secrets
This commit is contained in:
@@ -467,4 +467,42 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) =>
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change autoCapitilzation Rule of workspace
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const toggleAutoCapitalization = async (req: Request, res: Response) => {
|
||||
let workspace;
|
||||
try {
|
||||
const { workspaceId } = req.params;
|
||||
const { autoCapitalization } = req.body;
|
||||
|
||||
workspace = await Workspace.findOneAndUpdate(
|
||||
{
|
||||
_id: workspaceId
|
||||
},
|
||||
{
|
||||
autoCapitalization
|
||||
},
|
||||
{
|
||||
new: true
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to change autoCapitalization setting'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
message: 'Successfully changed autoCapitalization setting',
|
||||
workspace
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface IWorkspace {
|
||||
name: string;
|
||||
slug: string;
|
||||
}>;
|
||||
autoCapitalization: boolean;
|
||||
}
|
||||
|
||||
const workspaceSchema = new Schema<IWorkspace>({
|
||||
@@ -15,6 +16,10 @@ const workspaceSchema = new Schema<IWorkspace>({
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
autoCapitalization: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'Organization',
|
||||
|
||||
@@ -118,4 +118,19 @@ router.delete( // TODO - rewire dashboard to this route
|
||||
workspaceController.deleteWorkspaceMembership
|
||||
);
|
||||
|
||||
|
||||
router.patch(
|
||||
'/:workspaceId/auto-capitalization',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
}),
|
||||
param('workspaceId').exists().trim(),
|
||||
body('autoCapitalization').exists().trim().notEmpty(),
|
||||
validateRequest,
|
||||
workspaceController.toggleAutoCapitalization
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -9,5 +9,7 @@
|
||||
"project-id-description": "To integrate Infisical into your code base and get automatic injection of environmental variables, you should use the following Project ID.",
|
||||
"project-id-description2": "For more guidance, including code snipets for various languages and frameworks, see ",
|
||||
"auto-generated": "This is your project's auto-generated unique identifier. It can't be changed.",
|
||||
"docs": "Infisical Docs"
|
||||
"docs": "Infisical Docs",
|
||||
"auto-capitalization": "Auto Capitalization",
|
||||
"auto-capitalization-description": "According to standards, Infisical will automatically capitalize your keys. If you want to disable this feature, you can do so here."
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ interface DashboardInputFieldProps {
|
||||
type: 'varName' | 'value' | 'comment';
|
||||
blurred?: boolean;
|
||||
isDuplicate?: boolean;
|
||||
isCapitalized?: boolean;
|
||||
overrideEnabled?: boolean;
|
||||
modifyValueOverride?: (value: string | undefined, position: number) => void;
|
||||
isSideBarOpen?: boolean;
|
||||
@@ -41,6 +42,7 @@ const DashboardInputField = ({
|
||||
value,
|
||||
blurred,
|
||||
isDuplicate,
|
||||
isCapitalized,
|
||||
overrideEnabled,
|
||||
modifyValueOverride,
|
||||
isSideBarOpen
|
||||
@@ -69,7 +71,7 @@ const DashboardInputField = ({
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
onChange={(e) => onChangeHandler(e.target.value.toUpperCase(), position)}
|
||||
onChange={(e) => onChangeHandler(isCapitalized ? e.target.value.toUpperCase() : e.target.value, position)}
|
||||
type={type}
|
||||
value={value}
|
||||
className={`z-10 peer font-mono ph-no-capture bg-transparent h-full caret-bunker-200 text-sm px-2 w-full min-w-16 outline-none ${
|
||||
@@ -230,6 +232,7 @@ function inputPropsAreEqual(prev: DashboardInputFieldProps, next: DashboardInput
|
||||
prev.type === next.type &&
|
||||
prev.position === next.position &&
|
||||
prev.blurred === next.blurred &&
|
||||
prev.isCapitalized === next.isCapitalized &&
|
||||
prev.overrideEnabled === next.overrideEnabled &&
|
||||
prev.isDuplicate === next.isDuplicate &&
|
||||
prev.isSideBarOpen === next.isSideBarOpen
|
||||
|
||||
@@ -18,6 +18,7 @@ interface KeyPairProps {
|
||||
toggleSidebar: (id: string) => void;
|
||||
sidebarSecretId: string;
|
||||
isSnapshot: boolean;
|
||||
isCapitalized: boolean;
|
||||
deleteRow?: (props: DeleteRowFunctionProps) => void;
|
||||
tags: Tag[];
|
||||
togglePITSidebar?: (value: boolean) => void;
|
||||
@@ -75,6 +76,7 @@ const KeyPair = ({
|
||||
isDuplicate,
|
||||
toggleSidebar,
|
||||
sidebarSecretId,
|
||||
isCapitalized,
|
||||
isSnapshot,
|
||||
deleteRow,
|
||||
togglePITSidebar,
|
||||
@@ -97,6 +99,7 @@ const KeyPair = ({
|
||||
<div className='text-bunker-400 text-xs flex items-center justify-center w-14 h-10 cursor-default'>{keyPair.pos + 1}</div>
|
||||
<div className="flex items-center max-h-16">
|
||||
<DashboardInputField
|
||||
isCapitalized = {isCapitalized}
|
||||
onChangeHandler={modifyKey}
|
||||
type="varName"
|
||||
position={keyPair.pos}
|
||||
|
||||
@@ -5,4 +5,6 @@ export {
|
||||
useGetUserWorkspaces,
|
||||
useGetWorkspaceById,
|
||||
useRenameWorkspace,
|
||||
useToggleAutoCapitalization,
|
||||
useUpdateWsEnvironment} from './queries';
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
DeleteEnvironmentDTO,
|
||||
DeleteWorkspaceDTO,
|
||||
RenameWorkspaceDTO,
|
||||
ToggleAutoCapitalizationDTO,
|
||||
UpdateEnvironmentDTO,
|
||||
Workspace
|
||||
} from './types';
|
||||
@@ -51,6 +52,18 @@ export const useRenameWorkspace = () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useToggleAutoCapitalization = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<{}, {}, ToggleAutoCapitalizationDTO>({
|
||||
mutationFn: ({ workspaceID, state }) =>
|
||||
apiRequest.patch(`/api/v2/workspace/${workspaceID}/auto-capitalization`, { autoCapitalization: state }),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteWorkspace = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ export type Workspace = {
|
||||
_id: string;
|
||||
name: string;
|
||||
organization: string;
|
||||
autoCapitalization: boolean;
|
||||
environments: WorkspaceEnv[];
|
||||
};
|
||||
|
||||
@@ -11,6 +12,7 @@ export type WorkspaceTag = { _id: string; name: string; slug: string };
|
||||
|
||||
// mutation dto
|
||||
export type RenameWorkspaceDTO = { workspaceID: string; newWorkspaceName: string };
|
||||
export type ToggleAutoCapitalizationDTO = { workspaceID: string; state: boolean };
|
||||
|
||||
export type DeleteWorkspaceDTO = { workspaceID: string };
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ interface Workspace {
|
||||
__v: number;
|
||||
_id: string;
|
||||
name: string;
|
||||
autoCapitalization: boolean;
|
||||
organization: string;
|
||||
environments: Array<{ name: string; slug: string }>;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ export default function Dashboard() {
|
||||
const [snapshotData, setSnapshotData] = useState<SnapshotProps>();
|
||||
const [numSnapshots, setNumSnapshots] = useState<number>();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const [autoCapitalization, setAutoCapitalization] = useState(false);
|
||||
const [dropZoneData, setDropZoneData] = useState<SecretDataProps[]>();
|
||||
const [projectTags, setProjectTags] = useState<Tag[]>([]);
|
||||
|
||||
@@ -224,6 +225,7 @@ export default function Dashboard() {
|
||||
if (!workspace) {
|
||||
router.push(`/dashboard/${userWorkspaces?.[0]?._id}`);
|
||||
}
|
||||
setAutoCapitalization(workspace?.autoCapitalization ?? true);
|
||||
|
||||
const accessibleEnvironments = await getWorkspaceEnvironments({ workspaceId });
|
||||
setWorkspaceEnvs(accessibleEnvironments || []);
|
||||
@@ -874,6 +876,7 @@ export default function Dashboard() {
|
||||
.filter((row) => !sharedToHide.includes(row.id))
|
||||
.map((keyPair) => (
|
||||
<KeyPair
|
||||
isCapitalized={autoCapitalization}
|
||||
key={keyPair.id}
|
||||
keyPair={keyPair}
|
||||
modifyValue={listenChangeValue}
|
||||
@@ -916,6 +919,7 @@ export default function Dashboard() {
|
||||
)
|
||||
.map((keyPair) => (
|
||||
<KeyPair
|
||||
isCapitalized={autoCapitalization}
|
||||
key={keyPair.id}
|
||||
keyPair={keyPair}
|
||||
modifyValue={listenChangeValue}
|
||||
|
||||
@@ -13,6 +13,7 @@ const ProjectSettings = () => {
|
||||
<title>{t('common:head-title', { title: t('settings-project:title') })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
|
||||
<ProjectSettingsPage />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -27,10 +27,15 @@ import {
|
||||
useGetUserWsServiceTokens,
|
||||
useGetWsTags,
|
||||
useRenameWorkspace,
|
||||
useToggleAutoCapitalization,
|
||||
useUpdateWsEnvironment
|
||||
} from '@app/hooks/api';
|
||||
|
||||
|
||||
import { AutoCapitalizationSection } from './components/AutoCapitalizationSection/AutoCapitalizationSection';
|
||||
|
||||
import { SecretTagsSection } from './components/SecretTagsSection';
|
||||
|
||||
import {
|
||||
CopyProjectIDSection,
|
||||
CreateServiceToken,
|
||||
@@ -55,6 +60,8 @@ export const ProjectSettingsPage = () => {
|
||||
const [isDeleting, setIsDeleting] = useToggle();
|
||||
|
||||
const renameWorkspace = useRenameWorkspace();
|
||||
const toggleAutoCapitalization = useToggleAutoCapitalization();
|
||||
|
||||
const deleteWorkspace = useDeleteWorkspace();
|
||||
// env crud operation
|
||||
const createWsEnv = useCreateWsEnvironment();
|
||||
@@ -93,6 +100,26 @@ export const ProjectSettingsPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onAutoCapitalizationToggle = async (state: boolean) => {
|
||||
try {
|
||||
await toggleAutoCapitalization.mutateAsync({
|
||||
workspaceID,
|
||||
state
|
||||
});
|
||||
const text = `Successfully ${state ? 'enabled' : 'disabled'} auto capitalization`;
|
||||
createNotification({
|
||||
text,
|
||||
type: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
createNotification({
|
||||
text: 'Failed to update auto capitalization',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onDeleteWorkspace = async () => {
|
||||
setIsDeleting.on();
|
||||
try {
|
||||
@@ -289,6 +316,10 @@ export const ProjectSettingsPage = () => {
|
||||
workspaceName={currentWorkspace?.name}
|
||||
onProjectNameChange={onRenameWorkspace}
|
||||
/>
|
||||
<AutoCapitalizationSection
|
||||
workspaceAutoCapitalization={currentWorkspace?.autoCapitalization}
|
||||
onAutoCapitalizationChange={onAutoCapitalizationToggle}
|
||||
/>
|
||||
<CopyProjectIDSection workspaceID={currentWorkspace?._id || ''} />
|
||||
<EnvironmentSection
|
||||
environments={currentWorkspace?.environments || []}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Checkbox } from '@app/components/v2';
|
||||
|
||||
type Props = {
|
||||
workspaceAutoCapitalization?: boolean;
|
||||
onAutoCapitalizationChange: (state: boolean) => Promise<void>;
|
||||
};
|
||||
|
||||
export const AutoCapitalizationSection = ({
|
||||
workspaceAutoCapitalization,
|
||||
onAutoCapitalizationChange
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<form>
|
||||
<div className="mb-2 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pb-6 pt-2">
|
||||
<p className="mb-4 mt-2 text-xl font-semibold">
|
||||
{t('settings-project:auto-capitalization')}
|
||||
</p>
|
||||
<Checkbox
|
||||
className="data-[state=checked]:bg-primary"
|
||||
id="autoCapitalization"
|
||||
isChecked={workspaceAutoCapitalization}
|
||||
onCheckedChange={(state) => {
|
||||
onAutoCapitalizationChange(state as boolean);
|
||||
}}
|
||||
>
|
||||
{t('settings-project:auto-capitalization-description')}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { AutoCapitalizationSection } from './AutoCapitalizationSection';
|
||||
Reference in New Issue
Block a user