mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
added user controller and modified auth method page
This commit is contained in:
@@ -148,6 +148,43 @@ export const updateAuthProvider = async (req: Request, res: Response) => {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update auth provider of the current user to [authProvider]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const updateAuthProviders = async (req: Request, res: Response) => {
|
||||
const {
|
||||
authProviders
|
||||
} = req.body;
|
||||
|
||||
if (
|
||||
req.user?.authProvider === AuthProvider.OKTA_SAML
|
||||
|| req.user?.authProvider === AuthProvider.AZURE_SAML
|
||||
|| req.user?.authProvider === AuthProvider.JUMPCLOUD_SAML
|
||||
) {
|
||||
return res.status(400).send({
|
||||
message: "Failed to update user authentication method because SAML SSO is enforced"
|
||||
});
|
||||
}
|
||||
|
||||
const user = await User.findByIdAndUpdate(
|
||||
req.user._id.toString(),
|
||||
{
|
||||
authProviders
|
||||
},
|
||||
{
|
||||
new: true
|
||||
}
|
||||
);
|
||||
|
||||
return res.status(200).send({
|
||||
user
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return organizations that the current user is part of.
|
||||
* @param req
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface IUser extends Document {
|
||||
_id: Types.ObjectId;
|
||||
authId?: string;
|
||||
authProvider?: AuthProvider;
|
||||
authProviders?: AuthProvider[];
|
||||
email: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
|
||||
@@ -57,6 +57,24 @@ router.patch(
|
||||
usersController.updateAuthProvider
|
||||
);
|
||||
|
||||
router.put(
|
||||
"/me/auth-providers",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY],
|
||||
}),
|
||||
body("authProviders").exists().isArray({
|
||||
min: 1,
|
||||
}).custom((authProviders: AuthProvider[]) => {
|
||||
return authProviders.every(provider => [
|
||||
AuthProvider.EMAIL,
|
||||
AuthProvider.GOOGLE,
|
||||
AuthProvider.GITHUB
|
||||
].includes(provider))
|
||||
}),
|
||||
validateRequest,
|
||||
usersController.updateAuthProviders,
|
||||
);
|
||||
|
||||
router.get(
|
||||
"/me/organizations",
|
||||
requireAuth({
|
||||
|
||||
@@ -16,6 +16,7 @@ type Props = {
|
||||
position?: "item-aligned" | "popper";
|
||||
isDisabled?: boolean;
|
||||
icon?: IconProp;
|
||||
isMulti?: boolean;
|
||||
};
|
||||
|
||||
export type SelectProps = Omit<SelectPrimitive.SelectProps, "disabled"> & Props;
|
||||
|
||||
@@ -15,5 +15,6 @@ export {
|
||||
useRegisterUserAction,
|
||||
useRevokeMySessions,
|
||||
useUpdateOrgUserRole,
|
||||
useUpdateUserAuthProvider
|
||||
useUpdateUserAuthProvider,
|
||||
useUpdateUserAuthProviders,
|
||||
} from "./queries";
|
||||
|
||||
@@ -80,6 +80,28 @@ export const useUpdateUserAuthProvider = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const useUpdateUserAuthProviders = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
authProviders
|
||||
}: {
|
||||
authProviders: string[];
|
||||
}) => {
|
||||
const { data: { user } } = await apiRequest.put("/api/v2/users/me/auth-providers", {
|
||||
authProviders
|
||||
});
|
||||
|
||||
return user;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(userKeys.getUser);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetUserAction = (action: string) =>
|
||||
useQuery({
|
||||
queryKey: userKeys.userAction,
|
||||
|
||||
@@ -13,6 +13,7 @@ export type User = {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
authProvider?: AuthProvider;
|
||||
authProviders?: AuthProvider[];
|
||||
encryptionVersion?: number;
|
||||
protectedKey?: string;
|
||||
protectedKeyIV?: string;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
Select,
|
||||
SelectItem} from "@app/components/v2";
|
||||
Checkbox
|
||||
} from "@app/components/v2";
|
||||
import { useUser } from "@app/context";
|
||||
import {
|
||||
useUpdateUserAuthProvider
|
||||
useUpdateUserAuthProviders
|
||||
} from "@app/hooks/api";
|
||||
|
||||
const authMethods = [
|
||||
@@ -24,7 +23,7 @@ const authMethods = [
|
||||
];
|
||||
|
||||
const schema = yup.object({
|
||||
authMethod: yup.string().required("Auth method is required")
|
||||
authMethods: yup.array().required("Auth method is required")
|
||||
});
|
||||
|
||||
export type FormData = yup.InferType<typeof schema>;
|
||||
@@ -32,35 +31,38 @@ export type FormData = yup.InferType<typeof schema>;
|
||||
export const AuthMethodSection = () => {
|
||||
const { createNotification } = useNotificationContext();
|
||||
const { user } = useUser();
|
||||
const { mutateAsync, isLoading } = useUpdateUserAuthProvider();
|
||||
const { mutateAsync, isLoading } = useUpdateUserAuthProviders();
|
||||
|
||||
const {
|
||||
reset,
|
||||
control,
|
||||
handleSubmit
|
||||
handleSubmit,
|
||||
setValue,
|
||||
watch,
|
||||
} = useForm<FormData>({
|
||||
defaultValues: {
|
||||
authMethod: user?.authProvider ?? "email"
|
||||
authMethods: [user?.authProvider ?? "email"]
|
||||
},
|
||||
resolver: yupResolver(schema)
|
||||
});
|
||||
|
||||
const selectedAuthMethods = watch("authMethods");
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
reset({
|
||||
authMethod: user?.authProvider ?? "email"
|
||||
authMethods: [user?.authProvider ?? "email"]
|
||||
});
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
const onFormSubmit = async ({
|
||||
authMethod
|
||||
authMethods
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (
|
||||
authMethod === "okta-saml"
|
||||
|| authMethod === "azure-saml"
|
||||
|| authMethod === "jumpcloud-saml"
|
||||
authMethods.includes("okta-saml")
|
||||
|| authMethods.includes("azure-saml")
|
||||
|| authMethods.includes("jumpcloud-saml")
|
||||
) {
|
||||
createNotification({
|
||||
text: "SAML authentication can only be configured in your organization settings",
|
||||
@@ -71,7 +73,7 @@ export const AuthMethodSection = () => {
|
||||
}
|
||||
|
||||
await mutateAsync({
|
||||
authProvider: authMethod
|
||||
authProviders: authMethods
|
||||
});
|
||||
|
||||
createNotification({
|
||||
@@ -96,36 +98,29 @@ export const AuthMethodSection = () => {
|
||||
Authentication Method
|
||||
</h2>
|
||||
<div className="max-w-md mb-4">
|
||||
<Controller
|
||||
control={control}
|
||||
name="authMethod"
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
className="mb-0"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Select
|
||||
defaultValue={field.value}
|
||||
{...field}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full bg-mineshaft-800 border border-mineshaft-600"
|
||||
>
|
||||
{authMethods.map((authMethod) => {
|
||||
return (
|
||||
<SelectItem
|
||||
value={authMethod.value}
|
||||
key={`auth-method-${authMethod.value}`}
|
||||
>
|
||||
{authMethod.label}
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{
|
||||
authMethods.map(authMethod => (
|
||||
<Checkbox
|
||||
className="data-[state=checked]:bg-primary"
|
||||
id={`auth-method-id-${authMethod.label}`}
|
||||
key={`auth-method-${authMethod.label}`}
|
||||
isChecked={selectedAuthMethods.includes(authMethod.value)}
|
||||
onCheckedChange={(checked) => {
|
||||
if (checked) {
|
||||
setValue("authMethods", [
|
||||
...selectedAuthMethods,
|
||||
authMethod.value
|
||||
])
|
||||
} else {
|
||||
setValue("authMethods", selectedAuthMethods.filter(auth => auth !== authMethod.value))
|
||||
}
|
||||
}}>
|
||||
{authMethod.label}
|
||||
</Checkbox>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
colorSchema="secondary"
|
||||
@@ -136,4 +131,4 @@ export const AuthMethodSection = () => {
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user