I am developing a log in system in NestJS using TypeORM and Postgres. In my login options, I propose the user to use a couple email / password or to use an OAuth authentication. But once an account is created, they are not mutually exclusive (a user can have an email + password and a Google account attached to his account, for example).
Therefore, I would like to make the password OR the OAuthLogin nullable, but at least one of them should never be nullable.
Is it possible to achieve this with TypeORM ?
@Entity()
class User {
@PrimaryGeneratedColumn()
public id: number;
@Column({ unique: true })
public email: string;
@Column({ nullable: true })
@Exclude()
public password?: string;
@JoinColumn()
@OneToMany(() => OAuthLogin, (provider: OAuthLogin) => provider.user, {
cascade: true,
})
public oAuthLogins: OAuthLogin[];
}
export default User;
(P. S.: for my current code, I chose to make the password only nullable...)
The short answer is no, not at the TypeORM level. However, you can achieve this in your application code using the ValidateIf
decorator from class-validator
:
@Column({ nullable: true })
@Exclude()
@IsNotEmpty()
@ValidateIf(u => !u.oAuthLogins || u.oAuthLogins.length === 0)
public password?: string;
@JoinColumn()
@IsArray()
@ValidateIf(u => !u.password)
@OneToMany(() => OAuthLogin, (provider: OAuthLogin) => provider.user, {
cascade: true,
})
public oAuthLogins?: OAuthLogin[];
Elsewhere in your application:
import { validate } from 'class-validator';
...
validate(user)
If this entity is crossing a controller, you can also use NestJS's ValidationPipe
to enforce this at the controller or application level:
// main.ts
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));