From 13fe129e4b33b07ebe13ff9529e7f7a66fbb49ec Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 17 Jul 2024 10:36:48 -0300 Subject: [PATCH] refactor: add queries and mutation for authentication refactor (#2754) * feat: add API endpoint for retrieving user data * feat: add useAddUser hook for adding a user via API * feat: add useGetUserPage hook for retrieving users with pagination * refactor: optimize deletion of messages (#2714) * feat: optimize deletion of messages in SessionView component This commit optimizes the deletion of messages in the SessionView component by using the useDeleteMessages hook from the API queries. It replaces the useRemoveMessages hook that was previously used. The new implementation handles the deletion of messages more efficiently and provides better error handling. The selectedRows state is updated after successful deletion, and a success message is displayed to the user. In case of an error, an error message is shown. Co-authored-by: Gabriel Luiz Freitas Almeida * feat: optimize deletion of messages in SessionView component This commit optimizes the deletion of messages in the SessionView component by using the useDeleteMessages hook from the API queries. It replaces the useRemoveMessages hook that was previously used. The new implementation handles the deletion of messages more efficiently and provides better error handling. The selectedRows state is updated after successful deletion, and a success message is displayed to the user. In case of an error, an error message is shown. Co-authored-by: Gabriel Luiz Freitas Almeida * refactor: optimize deletion of messages in SessionView component This commit optimizes the deletion of messages in the SessionView component by using the useDeleteMessages hook from the API queries. It replaces the useRemoveMessages hook that was previously used. The new implementation handles the deletion of messages more efficiently and provides better error handling. The selectedRows state is updated after successful deletion, and a success message is displayed to the user. In case of an error, an error message is shown. * [autofix.ci] apply automated fixes --------- Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Lucas Oliveira Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> * fix: component seems to be clickable (#2731) * Changed card to not have shadow on hover if it is a component * removed unused console.log * feat: add logs field to ResultData and Vertex class (#2732) * feat: add logs to ResultDataResponse in schemas.py * feat(schema.py): add logs field to ResultData class to store log messages for better debugging and monitoring * feat(vertex): add logs attribute to Vertex class to store logs for each vertex operation * feat: add useDeleteUsers hook for deleting users via API * feat: add useUpdateUser hook for updating user data via API * feat: add useResetPassword hook for resetting user password via API * feat: add logout API endpoint and useLogout hook Add the `logout` API endpoint and the `useLogout` hook to handle user logout functionality. The `logout` API endpoint sends a PATCH request to the server to log out the user, while the `useLogout` hook provides a convenient way to call the `logout` API endpoint. This addition allows users to securely log out of the application. * feat: add login API endpoint and useLoginUser hook Add the `login` API endpoint and the `useLoginUser` hook to handle user login functionality. The `login` API endpoint sends a POST request to the server with the user's username and password to authenticate the user. The `useLoginUser` hook provides a convenient way to call the `login` API endpoint. This addition allows users to securely log in to the application. * feat: add autologin API endpoint and useGetAutoLogin hook Add the `autologin` API endpoint and the `useGetAutoLogin` hook to handle automatic login functionality. The `autologin` API endpoint sends a GET request to the server to check if the user is already logged in. The `useGetAutoLogin` hook provides a convenient way to call the `autologin` API endpoint. This addition allows for seamless automatic login for users who have previously logged in to the application. * feat: add REFRESH constant and useRefrshAccessToken hook Add the `REFRESH` constant to the `constants.ts` file and the `useRefrshAccessToken` hook to handle refreshing the access token. The `REFRESH` constant represents the API endpoint for refreshing the access token, and the `useRefrshAccessToken` hook provides a convenient way to call this endpoint. This addition allows for seamless token refreshing for authenticated users. * refactor: fromat code --------- Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Lucas Oliveira Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> --- .../custom/custom_component/component.py | 2 + .../src/controllers/API/helpers/constants.ts | 5 +++ .../src/controllers/API/queries/auth/index.ts | 1 + .../API/queries/auth/use-add-user.ts | 30 ++++++++++++++ .../API/queries/auth/use-delete-users.ts | 25 ++++++++++++ .../API/queries/auth/use-get-autologin.ts | 20 ++++++++++ .../API/queries/auth/use-get-user.ts | 20 ++++++++++ .../API/queries/auth/use-get-users-page.ts | 33 ++++++++++++++++ .../API/queries/auth/use-login-user.ts | 33 ++++++++++++++++ .../API/queries/auth/use-logout.ts | 26 +++++++++++++ .../API/queries/auth/use-refresh-access.ts | 22 +++++++++++ .../API/queries/auth/use-reset-password.ts | 39 +++++++++++++++++++ .../API/queries/auth/use-update-user.ts | 26 +++++++++++++ src/frontend/src/types/api/index.ts | 6 ++- 14 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 src/frontend/src/controllers/API/queries/auth/index.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-add-user.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-delete-users.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-get-autologin.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-get-user.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-get-users-page.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-login-user.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-logout.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-refresh-access.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-reset-password.ts create mode 100644 src/frontend/src/controllers/API/queries/auth/use-update-user.ts diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index af1dfe261..8df5f6c2b 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -9,6 +9,7 @@ from langflow.inputs.inputs import InputTypes from langflow.schema.artifact import get_artifact_type, post_process_raw from langflow.schema.data import Data from langflow.schema.message import Message +from langflow.services.tracing.schema import Log from langflow.template.field.base import UNDEFINED, Output from .custom_component import CustomComponent @@ -38,6 +39,7 @@ class Component(CustomComponent): inputs: List[InputTypes] = [] outputs: List[Output] = [] code_class_base_inheritance: ClassVar[str] = "Component" + _output_logs: dict[str, Log] = {} def __init__(self, **data): self._inputs: dict[str, InputTypes] = {} diff --git a/src/frontend/src/controllers/API/helpers/constants.ts b/src/frontend/src/controllers/API/helpers/constants.ts index 0276e73c6..871707887 100644 --- a/src/frontend/src/controllers/API/helpers/constants.ts +++ b/src/frontend/src/controllers/API/helpers/constants.ts @@ -7,6 +7,11 @@ export const URLs = { VERSION: `version`, MESSAGES: `monitor/messages`, STORE: `store`, + USERS: "users", + LOGOUT: `logout`, + LOGIN: `login`, + AUTOLOGIN: "auto_login", + REFRESH: "refresh", BUILD: `build`, } as const; diff --git a/src/frontend/src/controllers/API/queries/auth/index.ts b/src/frontend/src/controllers/API/queries/auth/index.ts new file mode 100644 index 000000000..49ecf2dc4 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/index.ts @@ -0,0 +1 @@ +export * from "./use-get-user"; diff --git a/src/frontend/src/controllers/API/queries/auth/use-add-user.ts b/src/frontend/src/controllers/API/queries/auth/use-add-user.ts new file mode 100644 index 000000000..11af8fd61 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-add-user.ts @@ -0,0 +1,30 @@ +import { Users, useMutationFunctionType } from "@/types/api"; +import { UserInputType } from "@/types/components"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useAddUser: useMutationFunctionType = ( + options?, +) => { + const { mutate } = UseRequestProcessor(); + + const addUserFunction = async ( + user: UserInputType, + ): Promise> => { + const res = await api.post(`${getURL("USERS")}`, user); + return res.data; + }; + + const mutation: UseMutationResult, any, UserInputType> = mutate( + ["useAddUser"], + async (payload: UserInputType) => { + const res = await addUserFunction(payload); + return res; + }, + options, + ); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-delete-users.ts b/src/frontend/src/controllers/API/queries/auth/use-delete-users.ts new file mode 100644 index 000000000..9eedf558f --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-delete-users.ts @@ -0,0 +1,25 @@ +import { useMutationFunctionType } from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface DeleteUserParams { + user_id: string; +} + +export const useDeleteMessages: useMutationFunctionType = ( + options?, +) => { + const { mutate } = UseRequestProcessor(); + + const deleteMessage = async ({ user_id }: DeleteUserParams): Promise => { + const res = await api.delete(`${getURL("USERS")}/${user_id}`); + return res.data; + }; + + const mutation: UseMutationResult = + mutate(["useDeleteMessages"], deleteMessage, options); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-get-autologin.ts b/src/frontend/src/controllers/API/queries/auth/use-get-autologin.ts new file mode 100644 index 000000000..f1f9a63bb --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-get-autologin.ts @@ -0,0 +1,20 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { Users, useQueryFunctionType } from "../../../../types/api"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useGetAutoLogin: useQueryFunctionType = () => { + const { query } = UseRequestProcessor(); + + const getIsAutoLogin = async () => { + const response = await api.get(`${getURL("AUTOLOGIN")}`); + return response["data"]; + }; + + const queryResult = query(["useGetAutoLogin"], getIsAutoLogin, { + placeholderData: keepPreviousData, + }); + + return queryResult; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-get-user.ts b/src/frontend/src/controllers/API/queries/auth/use-get-user.ts new file mode 100644 index 000000000..a5d368106 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-get-user.ts @@ -0,0 +1,20 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { Users, useQueryFunctionType } from "../../../../types/api"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useGetUserData: useQueryFunctionType = () => { + const { query } = UseRequestProcessor(); + + const getUserData = async () => { + const response = await api.get(`${getURL("USERS")}/whoami`); + return response["data"]; + }; + + const queryResult = query(["useGetUserData"], getUserData, { + placeholderData: keepPreviousData, + }); + + return queryResult; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-get-users-page.ts b/src/frontend/src/controllers/API/queries/auth/use-get-users-page.ts new file mode 100644 index 000000000..96a0e9ada --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-get-users-page.ts @@ -0,0 +1,33 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { Users, useQueryFunctionType } from "../../../../types/api"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface getUsersPageQueryParams { + skip: number; + limit: number; +} + +export const useGetUserPage: useQueryFunctionType< + getUsersPageQueryParams, + Users +> = ({ skip, limit }) => { + const { query } = UseRequestProcessor(); + + async function getUsersPage(): Promise> { + const res = await api.get( + `${getURL("USERS")}/?skip=${skip}&limit=${limit}`, + ); + if (res.status === 200) { + return res.data; + } + return []; + } + + const queryResult = query(["useGetUserPage"], getUsersPage, { + placeholderData: keepPreviousData, + }); + + return queryResult; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-login-user.ts b/src/frontend/src/controllers/API/queries/auth/use-login-user.ts new file mode 100644 index 000000000..d97395b03 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-login-user.ts @@ -0,0 +1,33 @@ +import { LoginType, changeUser, useMutationFunctionType } from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useLoginUser: useMutationFunctionType = (options?) => { + const { mutate } = UseRequestProcessor(); + + async function updateUser({ password, username }: LoginType): Promise { + const res = await api.post( + `${getURL("LOGIN")}`, + new URLSearchParams({ + username: username, + password: password, + }).toString(), + { + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }, + ); + return res.data; + } + + const mutation: UseMutationResult = mutate( + ["useLoginUser"], + updateUser, + options, + ); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-logout.ts b/src/frontend/src/controllers/API/queries/auth/use-logout.ts new file mode 100644 index 000000000..7119ae88f --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-logout.ts @@ -0,0 +1,26 @@ +import { + changeUser, + resetPasswordType, + useMutationFunctionType, +} from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useLogout: useMutationFunctionType = (options?) => { + const { mutate } = UseRequestProcessor(); + + async function logoutUser(): Promise { + const res = await api.patch(`${getURL("LOGOUT")}`); + return res.data; + } + + const mutation: UseMutationResult = mutate( + ["useLogout"], + logoutUser, + options, + ); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-refresh-access.ts b/src/frontend/src/controllers/API/queries/auth/use-refresh-access.ts new file mode 100644 index 000000000..c330a0ca9 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-refresh-access.ts @@ -0,0 +1,22 @@ +import { LoginType, changeUser, useMutationFunctionType } from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useRefrshAccessToken: useMutationFunctionType = (options?) => { + const { mutate } = UseRequestProcessor(); + + async function refreshAccess(): Promise { + const res = await api.post(`${getURL("REFRESH")}`); + return res.data; + } + + const mutation: UseMutationResult = mutate( + ["useRefrshAccessToken"], + refreshAccess, + options, + ); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-reset-password.ts b/src/frontend/src/controllers/API/queries/auth/use-reset-password.ts new file mode 100644 index 000000000..899fe44b0 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-reset-password.ts @@ -0,0 +1,39 @@ +import { + changeUser, + resetPasswordType, + useMutationFunctionType, +} from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface resetPasswordParams { + user_id: string; + password: resetPasswordType; +} + +export const useResetPassword: useMutationFunctionType = ( + options?, +) => { + const { mutate } = UseRequestProcessor(); + + async function resetPassword({ + user_id, + password, + }: resetPasswordParams): Promise { + const res = await api.patch( + `${getURL("USERS")}/${user_id}/reset-password`, + password, + ); + return res.data; + } + + const mutation: UseMutationResult< + resetPasswordParams, + any, + resetPasswordParams + > = mutate(["useResetPassword"], resetPassword, options); + + return mutation; +}; diff --git a/src/frontend/src/controllers/API/queries/auth/use-update-user.ts b/src/frontend/src/controllers/API/queries/auth/use-update-user.ts new file mode 100644 index 000000000..5cf671e50 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/auth/use-update-user.ts @@ -0,0 +1,26 @@ +import { changeUser, useMutationFunctionType } from "@/types/api"; +import { UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface UpdateUserParams { + user_id: string; + user: changeUser; +} + +export const useUpdateUser: useMutationFunctionType = ( + options?, +) => { + const { mutate } = UseRequestProcessor(); + + async function updateUser({ user_id, user }: UpdateUserParams): Promise { + const res = await api.patch(`${getURL("USERS")}/${user_id}`, user); + return res.data; + } + + const mutation: UseMutationResult = + mutate(["useUpdateUser"], updateUser, options); + + return mutation; +}; diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 9b93b3da1..c805325fa 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -259,6 +259,10 @@ export type MutationFunctionType = ( options?: Omit, "mutationFn" | "mutationKey">, ) => UseMutationResult; -export type useMutationFunctionType = ( +export type useMutationFunctionType< + Variables = any, + Data = any, + Error = any, +> = ( options?: Omit, "mutationFn" | "mutationKey">, ) => UseMutationResult;