diff --git a/packages/backend/src/graphql/mutation-resolvers.js b/packages/backend/src/graphql/mutation-resolvers.js index a695f6e9..f66ef243 100644 --- a/packages/backend/src/graphql/mutation-resolvers.js +++ b/packages/backend/src/graphql/mutation-resolvers.js @@ -31,7 +31,6 @@ import verifyConnection from './mutations/verify-connection.js'; // Converted mutations import deleteUser from './mutations/delete-user.ee.js'; -import login from './mutations/login.js'; const mutationResolvers = { createAppAuthClient, @@ -50,7 +49,6 @@ const mutationResolvers = { duplicateFlow, executeFlow, generateAuthUrl, - login, registerUser, resetConnection, updateAppAuthClient, diff --git a/packages/backend/src/graphql/mutations/login.js b/packages/backend/src/graphql/mutations/login.js deleted file mode 100644 index b0504570..00000000 --- a/packages/backend/src/graphql/mutations/login.js +++ /dev/null @@ -1,17 +0,0 @@ -import User from '../../models/user.js'; -import createAuthTokenByUserId from '../../helpers/create-auth-token-by-user-id.js'; - -const login = async (_parent, params) => { - const user = await User.query().findOne({ - email: params.input.email.toLowerCase(), - }); - - if (user && (await user.login(params.input.password))) { - const token = await createAuthTokenByUserId(user.id); - return { token, user }; - } - - throw new Error('User could not be found.'); -}; - -export default login; diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 98d254c4..36f78e8e 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -18,7 +18,6 @@ type Mutation { duplicateFlow(input: DuplicateFlowInput): Flow executeFlow(input: ExecuteFlowInput): executeFlowType generateAuthUrl(input: GenerateAuthUrlInput): AuthLink - login(input: LoginInput): Auth registerUser(input: RegisterUserInput): User resetConnection(input: ResetConnectionInput): Connection updateAppAuthClient(input: UpdateAppAuthClientInput): AppAuthClient @@ -152,11 +151,6 @@ enum ArgumentEnumType { string } -type Auth { - user: User - token: String -} - type AuthenticationStep { type: String name: String @@ -403,11 +397,6 @@ input UpdateCurrentUserInput { fullName: String } -input LoginInput { - email: String! - password: String! -} - input PermissionInput { action: String! subject: String! diff --git a/packages/backend/src/helpers/authentication.js b/packages/backend/src/helpers/authentication.js index b119915a..9f01d21d 100644 --- a/packages/backend/src/helpers/authentication.js +++ b/packages/backend/src/helpers/authentication.js @@ -53,7 +53,6 @@ const isAuthenticatedRule = rule()(isAuthenticated); export const authenticationRules = { Mutation: { '*': isAuthenticatedRule, - login: allow, registerUser: allow, }, }; diff --git a/packages/web/src/components/LoginForm/index.jsx b/packages/web/src/components/LoginForm/index.jsx index 6cf95fbc..3611417e 100644 --- a/packages/web/src/components/LoginForm/index.jsx +++ b/packages/web/src/components/LoginForm/index.jsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { useNavigate, Link as RouterLink } from 'react-router-dom'; -import { useMutation } from '@apollo/client'; import Paper from '@mui/material/Paper'; import Link from '@mui/material/Link'; import Typography from '@mui/material/Typography'; @@ -8,17 +7,20 @@ import LoadingButton from '@mui/lab/LoadingButton'; import useAuthentication from 'hooks/useAuthentication'; import useCloud from 'hooks/useCloud'; import * as URLS from 'config/urls'; -import { LOGIN } from 'graphql/mutations/login'; import Form from 'components/Form'; import TextField from 'components/TextField'; import useFormatMessage from 'hooks/useFormatMessage'; +import useCreateAccessToken from 'hooks/useCreateAccessToken'; +import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar'; function LoginForm() { const isCloud = useCloud(); const navigate = useNavigate(); const formatMessage = useFormatMessage(); + const enqueueSnackbar = useEnqueueSnackbar(); const authentication = useAuthentication(); - const [login, { loading }] = useMutation(LOGIN); + const { mutateAsync: createAccessToken, isPending: loading } = + useCreateAccessToken(); React.useEffect(() => { if (authentication.isAuthenticated) { @@ -27,13 +29,19 @@ function LoginForm() { }, [authentication.isAuthenticated]); const handleSubmit = async (values) => { - const { data } = await login({ - variables: { - input: values, - }, - }); - const { token } = data.login; - authentication.updateToken(token); + try { + const { email, password } = values; + const { data } = await createAccessToken({ + email, + password, + }); + const { token } = data; + authentication.updateToken(token); + } catch (error) { + enqueueSnackbar(error?.message || formatMessage('loginForm.error'), { + variant: 'error', + }); + } }; return ( diff --git a/packages/web/src/components/SignUpForm/index.ee.jsx b/packages/web/src/components/SignUpForm/index.ee.jsx index d155729a..3ae6d2bc 100644 --- a/packages/web/src/components/SignUpForm/index.ee.jsx +++ b/packages/web/src/components/SignUpForm/index.ee.jsx @@ -11,8 +11,10 @@ import * as URLS from 'config/urls'; import { REGISTER_USER } from 'graphql/mutations/register-user.ee'; import Form from 'components/Form'; import TextField from 'components/TextField'; -import { LOGIN } from 'graphql/mutations/login'; import useFormatMessage from 'hooks/useFormatMessage'; +import useCreateAccessToken from 'hooks/useCreateAccessToken'; +import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar'; + const validationSchema = yup.object().shape({ fullName: yup.string().trim().required('signupForm.mandatoryInput'), email: yup @@ -26,39 +28,57 @@ const validationSchema = yup.object().shape({ .required('signupForm.mandatoryInput') .oneOf([yup.ref('password')], 'signupForm.passwordsMustMatch'), }); + const initialValues = { fullName: '', email: '', password: '', confirmPassword: '', }; + function SignUpForm() { const navigate = useNavigate(); const authentication = useAuthentication(); const formatMessage = useFormatMessage(); + const enqueueSnackbar = useEnqueueSnackbar(); const [registerUser, { loading: registerUserLoading }] = useMutation(REGISTER_USER); - const [login, { loading: loginLoading }] = useMutation(LOGIN); + const { mutateAsync: createAccessToken, isPending: loginLoading } = + useCreateAccessToken(); + React.useEffect(() => { if (authentication.isAuthenticated) { navigate(URLS.DASHBOARD); } }, [authentication.isAuthenticated]); + const handleSubmit = async (values) => { const { fullName, email, password } = values; + await registerUser({ variables: { - input: { fullName, email, password }, + input: { + fullName, + email, + password, + }, }, }); - const { data } = await login({ - variables: { - input: { email, password }, - }, - }); - const { token } = data.login; - authentication.updateToken(token); + + try { + const { data } = await createAccessToken({ + email, + password, + }); + const { token } = data; + authentication.updateToken(token); + } catch (error) { + enqueueSnackbar(error?.message || formatMessage('signupForm.error'), { + variant: 'error', + }); + } }; + return ( ); } + export default SignUpForm; diff --git a/packages/web/src/graphql/mutations/login.js b/packages/web/src/graphql/mutations/login.js deleted file mode 100644 index c0f632a5..00000000 --- a/packages/web/src/graphql/mutations/login.js +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from '@apollo/client'; -export const LOGIN = gql` - mutation Login($input: LoginInput) { - login(input: $input) { - token - user { - id - email - } - } - } -`; diff --git a/packages/web/src/hooks/useCreateAccessToken.js b/packages/web/src/hooks/useCreateAccessToken.js new file mode 100644 index 00000000..28b5e33d --- /dev/null +++ b/packages/web/src/hooks/useCreateAccessToken.js @@ -0,0 +1,15 @@ +import { useMutation } from '@tanstack/react-query'; + +import api from 'helpers/api'; + +export default function useCreateAccessToken() { + const query = useMutation({ + mutationFn: async ({ email, password }) => { + const { data } = await api.post('/v1/access-tokens', { email, password }); + + return data; + }, + }); + + return query; +} diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 14a289f9..ba72f98b 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -144,6 +144,7 @@ "signupForm.validateEmail": "Email must be valid.", "signupForm.passwordsMustMatch": "Passwords must match.", "signupForm.mandatoryInput": "{inputName} is required.", + "signupForm.error": "Something went wrong. Please try again.", "loginForm.title": "Login", "loginForm.emailFieldLabel": "Email", "loginForm.passwordFieldLabel": "Password", @@ -152,6 +153,7 @@ "loginForm.noAccount": "Don't have an Automatisch account yet?", "loginForm.signUp": "Sign up", "loginPage.divider": "OR", + "loginForm.error": "Something went wrong. Please try again.", "ssoProviders.loginWithProvider": "Login with {providerName}", "forgotPasswordForm.title": "Forgot password", "forgotPasswordForm.submit": "Send reset instructions",