#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 }));