feat: enhance authentication flow with device info and optional POS flag in login DTO

This commit is contained in:
2026-05-11 19:09:04 +03:30
parent 5e6bd33cdd
commit 2a4e778c31
5 changed files with 125 additions and 30 deletions
+4 -1
View File
@@ -7,7 +7,10 @@ export class ApplicationAuthService {
constructor(private readonly authService: AuthService) {}
async login(data: applicationLoginDto) {
const loginResponse = await this.authService.login(data, true)
const loginResponse = await this.authService.login(data, true, {
id: data.device_id,
name: data.device_name,
})
return loginResponse
}
+4 -1
View File
@@ -1,3 +1,6 @@
import { LoginDto } from '@/modules/auth/dto/login.dto'
export class applicationLoginDto extends LoginDto {}
export class applicationLoginDto extends LoginDto {
device_name: string
device_id: string
}
+79 -22
View File
@@ -1,3 +1,4 @@
import { AccountInclude, AccountWhereUniqueInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable, NotFoundException } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
@@ -5,6 +6,10 @@ import 'dotenv/config'
import { AuthUtils } from './auth.utils'
import { LoginDto } from './dto/login.dto'
interface DeviceInfoForLogin {
id: string
name: string
}
@Injectable()
export class AuthService {
constructor(
@@ -12,36 +17,88 @@ export class AuthService {
private authUtils: AuthUtils,
) {}
async login(dto: LoginDto, isPos = false, deviceId?: string) {
const { username, password } = dto
async login(dto: LoginDto, is_pos = false, device_info?: DeviceInfoForLogin) {
const { username, password, isPos } = dto
const account = await this.prisma.$transaction(async tx => {
const account = await tx.account.findUnique({
where: {
username,
},
})
let accountWhere: AccountWhereUniqueInput = {
username,
}
if (!account) {
throw new NotFoundException('اطلاعات ورودی شما اشتباه است')
}
let accountInclude: AccountInclude = {}
if (isPos) {
const posAccount = await tx.consumerAccount.findUnique({
where: {
account_id: account.id,
},
})
if (!posAccount) {
throw new NotFoundException('اطلاعات ورودی شما اشتباه است')
}
}
// console.error('isPos', isPos)
return account
// if (isPos) {
// if (!device_info?.id) {
// throw new NotFoundException('اطلاعات ورودی شما اشتباه است')
// }
// accountWhere = {
// ...accountWhere,
// consumer_account: {
// pos: {
// isNot: null,
// },
// },
// }
// accountInclude = {
// ...accountInclude,
// consumer_account: {
// select: {
// id: true,
// account_device: true,
// },
// },
// }
// }
const account = await this.prisma.account.findUnique({
where: accountWhere,
include: accountInclude,
})
if (!account) {
throw new NotFoundException('اطلاعات ورودی شما اشتباه است')
}
await this.authUtils.checkAuthPassword(password, account.password)
// if (isPos) {
// if (!account.consumer_account) {
// throw new NotFoundException('اطلاعات ورودی شما اشتباه است')
// }
// const { account_device, id } = account.consumer_account as any
// if (account_device?.device_id !== device_info!.id) {
// throw new ForbiddenException(
// 'کاربر شما با دستگاه دیگری اجازه ورود دارد. لطفا با پشتیبانی تماس بگیرید',
// )
// }
// const device = await this.prisma.consumerAccountDevice.findUnique({
// where: {
// device_id: device_info!.id!,
// },
// })
// if (device) {
// throw new ForbiddenException(
// 'این دستگاه برای کاربر دیگری رجیستر شده است. لطفا با پشتیبانی تماس بگیرید.',
// )
// }
// await this.prisma.consumerAccountDevice.create({
// data: {
// device_id: device_info!.id!,
// device_name: device_info!.name,
// consumer_account: {
// connect: {
// id,
// },
// },
// },
// })
// }
const preparedData = await this.authUtils.generateLoginResponse(account)
return ResponseMapper.create(preparedData)
}
+6 -1
View File
@@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsString } from 'class-validator'
import { IsBoolean, IsOptional, IsString } from 'class-validator'
export class LoginDto {
@ApiProperty({ description: 'Mobile number used as username', example: '09120258156' })
@@ -9,4 +9,9 @@ export class LoginDto {
@ApiProperty({ description: 'OTP password (one-time password)', example: '11111' })
@IsString()
password: string
@ApiProperty({ default: false })
@IsBoolean()
@IsOptional()
isPos: boolean = false
}