This is my initial query on this platform.
I have successfully implemented login/register mutations, but I am now looking to add error handling functionality. Specifically, I want to display an error message stating "username incorrect" when the user enters an invalid username and a similar message for an incorrect password entry.
Currently, the error message only appears when an invalid username is entered, not when the password is incorrect. In the case of an incorrect password entry, it returns a null user object, as shown below:
{
"data": {
"login": {
"user": null
}
}
}
The register mutation works as intended, but fails to display errors when certain conditions are met, resulting in a null user response.
Below is the code snippet, with the login mutation located at the bottom and the register mutation above it.
Thank you!
import { User } from '../entities/User';
import { MyContext } from 'src/types';
import argon2 from 'argon2';
import {
Resolver,
Mutation,
Arg,
InputType,
Field,
Ctx,
ObjectType,
Query,
} from 'type-graphql';
@InputType()
class UsernamePasswordInput {
@Field()
username: string;
@Field()
password: string;
}
@ObjectType()
class FieldError {
@Field()
field: string;
message: string;
}
@ObjectType()
class UserResponse {
@Field(() => [FieldError], { nullable: true })
errors?: FieldError[];
@Field(() => User, { nullable: true })
user?: User;
}
// SAVE USER TO DATABASE
@Resolver()
export class UserResolver {
// GET ALL USERS
@Query(() => [User])
getAllUsers(@Ctx() { em }: MyContext): Promise<User[]> {
return em.find(User, {});
}
@Mutation(() => UserResponse)
async register(
@Arg('options') options: UsernamePasswordInput,
@Ctx() { em }: MyContext
): Promise<UserResponse> {
// username
if (options.username.length <= 2) {
return {
errors: [
{
field: 'username',
message: 'length must be greater than 2',
},
],
};
}
// password
if (options.password.length <= 3) {
return {
errors: [
{
field: 'password',
message: 'length must be greater than 3',
},
],
};
}
// hash password
const hashedPassword = await argon2.hash(options.password);
const user = em.create(User, {
username: options.username,
password: hashedPassword,
});
await em.persistAndFlush(user);
return {
user,
};
}
@Mutation(() => UserResponse)
async login(
@Arg('options') options: UsernamePasswordInput,
@Ctx() { em }: MyContext
): Promise<UserResponse> {
const user = await em.findOneOrFail(User, {
username: options.username,
});
if (!user) {
return {
errors: [
{
field: 'username',
message: ' incorrect username',
},
],
};
}
// verify the user password
const valid = await argon2.verify(user.password, options.password);
// if password is not valid, return errors
if (!valid) {
return {
errors: [
{
field: 'password',
message: 'incorrect password',
},
],
};
}
// return user
return {
user,
};
}
}