Тип или условный обнуляемый?

#postgresql #nestjs #typeorm

#postgresql #nestjs #typeorm

Вопрос:

Я разрабатываю систему входа в систему в NestJS с использованием TypeORM и Postgres. В моих параметрах входа я предлагаю пользователю использовать пару email / password или использовать аутентификацию OAuth. Но после создания учетной записи они не являются взаимоисключающими (например, у пользователя может быть адрес электронной почты пароль и учетная запись Google, привязанная к его учетной записи).

Поэтому я хотел бы сделать пароль ИЛИ OAuthLogin обнуляемыми, но по крайней мере один из них никогда не должен быть обнуляемым.

Возможно ли достичь этого с помощью 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.: для моего текущего кода я решил сделать пароль только обнуляемым …)

Комментарии:

1. Я не знаю о typeorm, но в postgres вам нужно сделать оба столбца обнуляемыми и добавить CHECK ограничение на таблицу с num_nonnulls(password, o_auth_logins) >= 1 помощью или чего-то подобного.

2. Я изучаю это: кажется, есть декоратор проверки, с помощью которого я могу выполнить некоторую проверку, но я не нахожу, как проверить, существует ли связь… @Check( «пароль» НЕ РАВЕН НУЛЮ ИЛИ «oAuthLogins» НЕ РАВЕН НУЛЮ ) , не работает, потому что Postgres ищет свойство oAuthLogins вместо отношения.

3. О, я пропустил, что это отношение, поскольку вы говорили о «обнуляемом». Нет, вы не можете этого сделать с помощью ограничения check. Если вы хотите сделать это на уровне базы данных, вам понадобится триггер.

4. Ну, на самом деле обнуляемым должно быть не отношение, а скорее данные на другом конце. Обработка данных отношений — это единственное, для чего не подходят ORM, и поэтому они немного усложняют ^^

Ответ №1:

Короткий ответ — нет, не на уровне TypeORM. Однако вы можете добиться этого в коде вашего приложения, используя ValidateIf декоратор из 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[];
  

В другом месте вашего приложения:

 import { validate } from 'class-validator';
...
validate(user)
  

Если этот объект пересекает контроллер, вы также можете использовать NestJS ValidationPipe для обеспечения этого на уровне контроллера или приложения:

 // main.ts
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));