Completed Features:
- Full JWT authentication system with refresh tokens
- User registration and login with device fingerprinting
- Child profile CRUD operations with permission-based access
- Family management with roles and permissions
- Database migrations for core auth and family structure
- Comprehensive test coverage (37 unit + E2E tests)
Tech Stack:
- NestJS backend with TypeORM
- PostgreSQL database
- JWT authentication with Passport
- bcrypt password hashing
- Docker Compose for infrastructure
🤖 Generated with Claude Code
66 lines
1.4 KiB
TypeScript
66 lines
1.4 KiB
TypeScript
import {
|
|
Entity,
|
|
Column,
|
|
PrimaryColumn,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
OneToMany,
|
|
BeforeInsert,
|
|
} from 'typeorm';
|
|
import { DeviceRegistry } from './device-registry.entity';
|
|
import { FamilyMember } from './family-member.entity';
|
|
|
|
@Entity('users')
|
|
export class User {
|
|
@PrimaryColumn({ length: 20 })
|
|
id: string;
|
|
|
|
@Column({ length: 255, unique: true })
|
|
email: string;
|
|
|
|
@Column({ length: 20, nullable: true })
|
|
phone?: string;
|
|
|
|
@Column({ name: 'password_hash', length: 255 })
|
|
passwordHash: string;
|
|
|
|
@Column({ length: 100 })
|
|
name: string;
|
|
|
|
@Column({ length: 10, default: 'en-US' })
|
|
locale: string;
|
|
|
|
@Column({ length: 50, default: 'UTC' })
|
|
timezone: string;
|
|
|
|
@Column({ name: 'email_verified', default: false })
|
|
emailVerified: boolean;
|
|
|
|
@CreateDateColumn({ name: 'created_at' })
|
|
createdAt: Date;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at' })
|
|
updatedAt: Date;
|
|
|
|
@OneToMany(() => DeviceRegistry, (device) => device.user)
|
|
devices: DeviceRegistry[];
|
|
|
|
@OneToMany(() => FamilyMember, (familyMember) => familyMember.user)
|
|
familyMemberships: FamilyMember[];
|
|
|
|
@BeforeInsert()
|
|
generateId() {
|
|
if (!this.id) {
|
|
this.id = `usr_${this.generateNanoId()}`;
|
|
}
|
|
}
|
|
|
|
private generateNanoId(): string {
|
|
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
let result = '';
|
|
for (let i = 0; i < 12; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
} |