feat: add simple login logic

This commit is contained in:
2026-02-18 09:13:23 +03:30
parent b9779f7cb6
commit e657264807
16 changed files with 259 additions and 13 deletions
+45
View File
@@ -0,0 +1,45 @@
import {
BeforeInsert,
Column,
CreateDateColumn,
Entity,
Index,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity()
@Index(['phone', 'used'])
export class OTP {
@PrimaryGeneratedColumn()
id: number;
@Index()
@Column({
type: 'varchar',
length: 11,
nullable: false,
})
phone: string;
@Column({
type: 'varchar',
length: 5,
nullable: false,
})
code: string;
@CreateDateColumn()
createdAt: Date;
@Index()
@Column({ type: 'timestamptz' })
expiredAt: Date;
@Column({ type: 'boolean', default: false })
used: boolean;
@BeforeInsert()
setExpiry() {
this.expiredAt = new Date(Date.now() + 2 * 60 * 1000);
}
}
+10
View File
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { OtpService } from './providers/otp.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { OTP } from './otp.entity';
@Module({
imports: [TypeOrmModule.forFeature([OTP])],
providers: [OtpService],
})
export class OtpModule {}
+39
View File
@@ -0,0 +1,39 @@
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { OTP } from '../otp.entity';
import { InjectRepository } from '@nestjs/typeorm';
@Injectable()
export class OtpService {
constructor(
/**
* Inject OTP Repository
*/
@InjectRepository(OTP)
private readonly otpRepository: Repository<OTP>,
) {}
/**
* Generate OTP 5-digit code
*/
private generateOTPCode(): string {
return Math.floor(10_000 + Math.random() * 90_000).toString();
}
/**
* Create new OTP record
*/
public async createOTP(phone: string): Promise<string> {
// OTP request Rate limit
const lastOTP = await this.otpRepository.findOne({
where: { phone },
order: { createdAt: 'DESC' },
});
if (lastOTP && Date.now() - lastOTP.createdAt.getTime() < 60_000) {
// throw new TooMany();
}
return '';
}
}