Marko Marchisio
Marko Marchisio

Reputation: 497

Nestjs - invalid input syntax for type integer: "[email protected]"

While creating the sign in controller and service i encountered the error mentioned in the title.

Users table

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column('varchar', { length: 50 })
  name;

  @Column('varchar', { length: 50 })
  surname;

  @Column('varchar', { length: 50 })
  street;

  @Column('varchar', { length: 50 })
  city;

  @Column('varchar', { length: 5 })
  zip;

  @Column({ type: 'int', nullable: true })
  rating;

  @Column('varchar', { length: 10 })
  phone;

  @Column('date')
  date;

  @Column({ type: 'varchar', length: 50, nullable: false, unique: true })
  email;

  @Column({ type: 'varchar', length: 75, nullable: false })
  password;
}

Sign in DTO

export class SignInDto {
  @IsNotEmpty()
  email: string;

  @IsNotEmpty()
  password: string;
}

Now, validation works when testing this in postman; if i enter just the email and leave out the password a proper error will show up.

Signing up on the other hand works just fine with this DTO:

export class SignUpDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsString()
  @IsNotEmpty()
  surname: string;

  @IsString()
  @IsNotEmpty()
  street: string;

  @IsString()
  @IsNotEmpty()
  city: string;

  @MinLength(5)
  @MaxLength(5)
  zip: string;

  rating: number;

  @IsString()
  @IsNotEmpty()
  phone: string;

  @IsDate()
  @Type(() => Date)
  @IsNotEmpty()
  date: Date;

  @IsEmail()
  @IsNotEmpty()
  email: string;

  @IsString()
  @MinLength(8)
  @MaxLength(32)
  @Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/)
  password: string;
}

Users repository

import {
  ConflictException,
  InternalServerErrorException,
} from '@nestjs/common';
import { EntityRepository, Repository } from 'typeorm';
import { SignUpDto } from './dto/signup.dto';
import { User } from './user.entity';
import * as bcrypt from 'bcrypt';

@EntityRepository(User)
export class UsersRepository extends Repository<User> {
  async createUser(signUpDto: SignUpDto): Promise<void> {
    const {
      name,
      surname,
      street,
      city,
      zip,
      rating,
      phone,
      date,
      email,
      password,
    } = signUpDto;

    const salt = await bcrypt.genSalt();
    const hashedPassword = await bcrypt.hash(password, salt);

    const user = this.create({
      name,
      surname,
      street,
      city,
      zip,
      rating,
      phone,
      date,
      email,
      password: hashedPassword,
    });
    try {
      await this.save(user);
    } catch (error) {
      if (error.code === '23505') {
        throw new ConflictException('User with the same e-mail already exists');
      } else {
        console.log(error);
        throw new InternalServerErrorException();
      }
    }
  }
}

Signup and Signin controller

import { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { SignInDto } from './dto/signin.dto';

import { SignUpDto } from './dto/signup.dto';

@Controller('auth')
export class AuthController {
  constructor(private authService: AuthService) {}

  @Post('/signup')
  signUp(@Body() signUpDto: SignUpDto): Promise<void> {
    return this.authService.signUp(signUpDto);
  }

  @Post('/signin')
  signIn(@Body() signInDto: SignInDto): Promise<string> {
    return this.authService.signIn(signInDto);
  }
}

Service where signup and signin logic is written

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(UsersRepository)
    private usersRepository: UsersRepository,
  ) {}

  async signUp(signUpDto: SignUpDto): Promise<void> {
    return this.usersRepository.createUser(signUpDto);
  }

  async signIn(signInDto: SignInDto): Promise<string> {
    const { email, password } = signInDto;
    const user = await this.usersRepository.findOne(email);
    if (user && (await bcrypt.compare(password, user.password))) {
      return 'success';
    } else {
      throw new UnauthorizedException('Check your login credentials');
    }
  }
}

Current database state

enter image description here

Error example enter image description here

HTTP request example enter image description here

Does anyone have any idea where to start with this? I mean, there is no way I defined the email as an integer?

Upvotes: 0

Views: 1656

Answers (1)

Jay McDoniel
Jay McDoniel

Reputation: 70191

TypeORM's findOne works based on ID if no specifier is given. You should be doing

async signIn(signInDto: SignInDto): Promise<string> {
  const { email, password } = signInDto;
  const user = await this.usersRepository.findOne({ email });
  if (user && (await bcrypt.compare(password, user.password))) {
    return 'success';
  } else {
    throw new UnauthorizedException('Check your login credentials');
  }
}

instead to tell TypeORM you're searching on the email and not on the ID

Upvotes: 2

Related Questions