Skip to content

Commit

Permalink
added user list table in user management tab of settings (#981)
Browse files Browse the repository at this point in the history
* added user list table in user management tab of settings

* renamed the user list data variable name

* edit user, delete user, change pasword

* invite user and send registration link
  • Loading branch information
harishshg authored Apr 7, 2023
1 parent 2f1bb08 commit be47fc9
Show file tree
Hide file tree
Showing 6 changed files with 909 additions and 1 deletion.
6 changes: 6 additions & 0 deletions deepfence_frontend/apps/dashboard/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export function getUserApiClient() {
const userApi = new UserApi(configuration);
return {
registerUser: userApi.registerUser.bind(userApi),
getUsers: userApi.getUsers.bind(userApi),
getUser: userApi.getUser.bind(userApi),
updateUser: userApi.updateUser.bind(userApi),
deleteUser: userApi.deleteUser.bind(userApi),
updatePassword: userApi.updatePassword.bind(userApi),
inviteUser: userApi.inviteUser.bind(userApi),
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { IconContext } from 'react-icons';
import { HiArrowSmLeft } from 'react-icons/hi';
import { Link, useFetcher } from 'react-router-dom';
import { ActionFunction, redirect } from 'react-router-dom';
import { toast } from 'sonner';
import { Button, Card, TextInput } from 'ui-components';

import { getUserApiClient } from '@/api/api';
import { ApiDocsBadRequestResponse } from '@/api/generated';
import { DFLink } from '@/components/DFLink';
import { SettingsTab } from '@/features/settings/components/SettingsTab';
import { ApiError, makeRequest } from '@/utils/api';

export type changePasswordActionReturnType = {
error?: string;
fieldErrors?: {
old_password?: string;
new_password?: string;
confirm_password?: string;
};
};

export const action: ActionFunction = async ({
request,
}): Promise<changePasswordActionReturnType> => {
const formData = await request.formData();
// add console_url which is the origin of request
formData.append('consoleUrl', window.location.origin);
const body = Object.fromEntries(formData);
if (body.new_password !== body.confirm_password) {
return {
fieldErrors: {
confirm_password: 'Password does not match',
},
};
}
const r = await makeRequest({
apiFunction: getUserApiClient().updatePassword,
apiArgs: [
{
modelUpdateUserPasswordRequest: {
old_password: body.new_password as string,
new_password: body.new_password as string,
},
},
],
errorHandler: async (r) => {
const error = new ApiError<changePasswordActionReturnType>({});
if (r.status === 400) {
const modelResponse: ApiDocsBadRequestResponse = await r.json();
return error.set({
fieldErrors: {
old_password: modelResponse.error_fields?.old_password as string,
new_password: modelResponse.error_fields?.new_password as string,
},
});
} else if (r.status === 403) {
const modelResponse: ApiDocsBadRequestResponse = await r.json();
return error.set({
error: modelResponse.message,
});
}
},
});

if (ApiError.isApiError(r)) {
return r.value();
}
toast.success('Password changed successfully');
throw redirect('/settings/user-management', 302);
};

const ChangePassword = () => {
const fetcher = useFetcher<changePasswordActionReturnType>();
const { data } = fetcher;
return (
<>
<SettingsTab value="user-management">
<div className="flex">
<DFLink
to="/settings/user-management"
className="shrink-0 flex items-center justify-start hover:no-underline active:no-underline focus:no-underline ml-5 mr-2 mt-2"
>
<IconContext.Provider
value={{
className: 'text-blue-600 dark:text-blue-500 ',
}}
>
<HiArrowSmLeft />
</IconContext.Provider>
<span className="text text-blue-600 dark:text-blue-500">Back</span>
</DFLink>
<span className="flex ml-2 mt-2 dark:text-white ">User Profile</span>
</div>
<Card className="flex-col p-5 mt-2 ml-5 gap-y-4">
<fetcher.Form method="post" className="flex flex-col gap-y-3">
<TextInput
label="Old Password"
type={'password'}
placeholder="Old Password"
name="old_password"
color={data?.fieldErrors?.old_password ? 'error' : 'default'}
sizing="sm"
className="w-3/4 min-[200px] max-w-xs"
helperText={data?.fieldErrors?.old_password}
required
/>
<TextInput
label="New Password"
type={'password'}
placeholder="New Password"
name="new_password"
sizing="sm"
className="w-3/4 min-[200px] max-w-xs"
color={data?.fieldErrors?.new_password ? 'error' : 'default'}
helperText={data?.fieldErrors?.new_password}
required
/>
<TextInput
label="Confirm Password"
type={'password'}
placeholder="Confirm Password"
name="confirm_password"
sizing="sm"
className="w-3/4 min-[200px] max-w-xs"
color={data?.fieldErrors?.confirm_password ? 'error' : 'default'}
helperText={data?.fieldErrors?.confirm_password}
required
/>
<Button
color="primary"
className="w-3/4 max-w-xs pl-3"
type="submit"
size="xs"
>
Change Password
</Button>
<Link to="/settings/user-management">
<Button color="danger" className="w-3/4 max-w-xs pl-3" size="xs">
Cancel
</Button>
</Link>
</fetcher.Form>
</Card>
</SettingsTab>
</>
);
};

export const module = {
element: <ChangePassword />,
action,
};
Loading

0 comments on commit be47fc9

Please sign in to comment.