Spaces:
Sleeping
Sleeping
File size: 3,280 Bytes
a38b26a 9f03bd9 a38b26a fcab6da a38b26a 37352d8 c235262 a38b26a 9f03bd9 a38b26a 9f03bd9 a38b26a 9f03bd9 a38b26a 9f03bd9 a38b26a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
DeleteDateColumn,
ManyToMany,
JoinTable,
OneToMany,
BeforeInsert,
BeforeUpdate,
} from 'typeorm';
import type { Relation } from 'typeorm';
import { Exclude } from 'class-transformer';
import * as bcrypt from 'bcrypt';
import { Role } from './role.entity';
import { Session } from './session.entity';
import { PasswordReset } from './password-reset.entity';
import { TwoFactorAuth } from './two-factor-auth.entity';
export enum UserStatus {
ACTIVE = 'active',
INACTIVE = 'inactive',
SUSPENDED = 'suspended',
PENDING = 'pending',
}
@Entity('users')
export class User {
@PrimaryGeneratedColumn({ type: 'bigint', unsigned: true, name: 'user_id' })
userId: number;
@Column({ unique: true, length: 100 })
email: string;
@Column({ name: 'password_hash', length: 255 })
@Exclude()
passwordHash: string;
@Column({ name: 'first_name', length: 50 })
firstName: string;
@Column({ name: 'last_name', length: 50 })
lastName: string;
@Column({ length: 20, nullable: true })
phone?: string;
@Column({ name: 'profile_picture_url', type: 'text', nullable: true })
profilePictureUrl?: string;
@Column({ type: 'text', nullable: true })
bio?: string;
@Column({ name: 'social_links', type: 'json', nullable: true })
socialLinks?: Record<string, string>;
@Column({ name: 'academic_interests', type: 'json', nullable: true })
academicInterests?: string[];
@Column({ name: 'skills', type: 'json', nullable: true })
skills?: string[];
@Column({ name: 'campus_id', nullable: true })
campusId?: number;
@Column({
type: 'enum',
enum: UserStatus,
default: UserStatus.PENDING,
})
status: UserStatus;
@Column({ name: 'email_verified', default: false })
emailVerified: boolean;
@Column({ name: 'last_login_at', type: 'datetime', nullable: true })
lastLoginAt?: Date;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
@DeleteDateColumn({ name: 'deleted_at', nullable: true })
deletedAt?: Date;
// Relationships
@ManyToMany(() => Role, (role) => role.users)
@JoinTable({
name: 'user_roles',
joinColumn: { name: 'user_id', referencedColumnName: 'userId' },
inverseJoinColumn: { name: 'role_id', referencedColumnName: 'roleId' },
})
roles: Relation<Role>[];
@OneToMany(() => Session, (session) => session.user)
sessions: Relation<Session>[];
@OneToMany(() => PasswordReset, (passwordReset) => passwordReset.user)
passwordResets: Relation<PasswordReset>[];
@OneToMany(() => TwoFactorAuth, (twoFactorAuth) => twoFactorAuth.user)
twoFactorAuths: Relation<TwoFactorAuth>[];
// Hooks for password hashing
@BeforeInsert()
@BeforeUpdate()
async hashPassword() {
if (this.passwordHash && !this.passwordHash.startsWith('$2b$')) {
this.passwordHash = await bcrypt.hash(this.passwordHash, 10);
}
}
// Method to validate password
async validatePassword(password: string): Promise<boolean> {
return bcrypt.compare(password, this.passwordHash);
}
// Computed property for full name
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
|